-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add Error message when sync is still in progress. #9475
Conversation
It looks like @seunlanlege hasn't signed our Contributor License Agreement, yet.
You can read and sign our full Contributor License Agreement at the following URL: https://cla.parity.io Once you've signed, please reply to this thread with Many thanks, Parity Technologies CLA Bot |
[clabot:check] |
It looks like @seunlanlege signed our Contributor License Agreement. 👍 Many thanks, Parity Technologies CLA Bot |
rpc/src/v1/impls/eth.rs
Outdated
if let Ok(SyncStatus::Info(_)) = self.syncing() { | ||
// alas, we're still syncing! | ||
warn!("Attempted to fetch transaction via hash while sync is in progress"); | ||
return Box::new(future::err(errors::ancient_block_missing())) |
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.
Isn't it possible to be in a syncing state even while we're quite close to the head of the chain? As a user I think I'd be surprised to see an error about "ancient" blocks if I were essentially synched. Maybe the error message should be something more generic like Block is unavailable
?
rpc/src/v1/impls/eth.rs
Outdated
if res.is_none() { | ||
if let Ok(SyncStatus::Info(_)) = self.syncing() { | ||
// alas, we're still syncing! | ||
warn!("Call made to transaction_by_block_hash_and_index while sync is in progress"); |
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.
Not sure that using the full method name here is a good idea. How about "RPC call is unavailable while synching"
.
rpc/src/v1/impls/eth.rs
Outdated
if let Ok(SyncStatus::Info(_)) = self.syncing() { | ||
// alas, we're still syncing! | ||
warn!("Attempted to fetch transaction via hash while sync is in progress"); | ||
return Box::new(future::err(errors::ancient_block_missing())) |
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.
Same comments from above apply here.
Maybe there's a way to add these warnings to all RPC calls higher up in the call chain so we don't have to pollute each method with log/warn calls?
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 don't think this is correct and I don't think it's easy to implement this properly. The main issue is that if I give you an hash how do you distinguish from you not having the data (because you're still syncing) or the data not existing in the first place? Also the current checks for self.syncing()
only check for normal sync as far as I remember, and even though I'm syncing I may already have the data available, e.g. I'm synced to block #2000 (but still syncing up to say #4000) and you ask for data from block #1000.
(reposting from private chat) I guess for some RPCs we could implement a best-effort approach. For example to fetch transaction by hash:
Can we use this strategy for all RPC methods? Do we want to implement something like this? |
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.
As in #9188 (comment) it's not really possible to implement this with significant changes to snapshot format. What's more I don't really think it's a good idea to store the tx hashes in snapshots anyway (perhaps we could store at most a bloom filter).
That said, I like @andresilva's suggestion to return an error instead of None
in case we know we have not fetched ancient blocks yet (note it's very different from syncing, so self.syncing()
is not the right method to use here).
If Andre's suggestion gets implemented we should also consider disabling that behaviour in case someone is consciously running with --no-ancient-blocks
.
#7411 might be a bit more straightforward - we have the block number there so we can just return an error in case |
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.
Still incorrect, but better. We're almost there.
rpc/src/v1/helpers/errors.rs
Outdated
RpcResult<Option<T>> { | ||
move |res| { | ||
if res.is_none() { | ||
if let Ok(SyncStatus::Info(_)) = sync_status { |
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.
The syncing state doesn't really matter, unless there is a variant that tells you that: "The chain is incomplete - We are still syncing/importing ancient blocks" (Which is completely different than regular sync, some more details about warp sync: https://wiki.parity.io/Warp-Sync.html)
rpc/src/v1/impls/eth.rs
Outdated
if let BlockNumber::Num(number) = num { | ||
match self.client.chain_info().best_block_number { | ||
BlockNumber::Num(best_block_number) => { | ||
if num < best_block_number { |
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.
This is quite wrong, actually these are the only queries that make sense at all, since:
- In database we store blocks from
[0...best_block_number]
- Querying anything from that range should succeed
- Querying anything greater than
best_block_number
will always fail
With ancient blocks the case is that the database is not complete, so we have a situation where:
- We have
[0..best_ancient_block] ... [first_block .. best_block]
- The latter range has been restored together with the snapshot
- The former range has been downloaded during ancient block import
- Any query that tries to get
num < best_block_number
and fails (i.e. returnsNone
) most likely falls into(best_ancient_block .. first_block)
range, so we should detect that and return the error only in such case.
rpc/src/v1/impls/eth.rs
Outdated
fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> BoxFuture<Option<RichBlock>> { | ||
Box::new(future::done(self.rich_block(num.into(), include_txs))) | ||
let result = self.check_block_existence(num) | ||
.and_then(|_| self.rich_block(num.into(), include_txs)); |
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.
To make it correct you should:
- First query the block
- If it's
None
andnum < best_block_number
return ancient block unavailable error.
Despite trying hard, I still can't manage to know all issues by number :) Having a human understandable description and title for a PR is therefore requested! |
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.
Overall LGTM. Just minor comments.
rpc/src/v1/helpers/errors.rs
Outdated
return Err(Error { | ||
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), | ||
// this error message feels pretty straightforward to me. ¯\_(ツ)_/¯ | ||
message: "We cannot tell for sure if the thing you requested is not available or we just don't have it".into(), |
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.
Probably better to be explicit about it? "Ancient block sync is still in progress."
rpc/src/v1/helpers/errors.rs
Outdated
let BlockChainInfo { ancient_block_hash, first_block_hash, .. } = client.chain_info(); | ||
// block information was requested, but unfortunately we couldn't find it and there | ||
// are gaps in the database ethcore/src/blockchain/blockchain.rs:202 | ||
if ancient_block_hash.is_some() && first_block_hash.is_some() { |
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 first_block_hash will always be some.
rpc/src/v1/helpers/errors.rs
Outdated
pub fn unavailable_block() -> Error { | ||
Error { | ||
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), | ||
message: "Block is unavailable".into(), |
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.
Probably better to have a more explicit message about ancient block sync?
Please rebase/merge master to fix conflicts. |
d8c0cd2
to
904daaf
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.
lgtm, minor grumble regarding error message - we can distinguish between:
- Knowing for sure that the blocks is not there because of ancient sync
- Assuming that it might be not found, because we don't have all the blocks yet.
Also I believe if we merge that we should also have an option to disable this behaviour since it's a breaking change (instead of returning Ok(None)
we return an Error
)
rpc/src/v1/helpers/errors.rs
Outdated
{ | ||
move |response| { | ||
if response.is_none() { | ||
let BlockChainInfo { ancient_block_hash, first_block_hash, .. } = client.chain_info(); |
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.
first_block_hash
is unused
rpc/src/v1/helpers/errors.rs
Outdated
// block information was requested, but unfortunately we couldn't find it and there | ||
// are gaps in the database ethcore/src/blockchain/blockchain.rs:202 | ||
if ancient_block_hash.is_some() { | ||
return Err(unavailable_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.
This is a bit different than check_block_number_existence
. Here we are unsure if the block is not valid or was not found, in the former we actually have certainty that the block is missing because we are still syncing ancient blocks.
TBH I think we should express that in the error message as well.
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.
Current changes LGTM. A few grumbles. And I think there're also other APIs in eth_
namespace that can apply the same strategy:
block_transaction_count_by_hash
block_transaction_count_by_number
block_uncles_count_by_hash
block_uncles_count_by_number
uncle_by_block_hash_and_index
uncle_by_block_number_and_index
parity/cli/mod.rs
Outdated
@@ -1230,6 +1234,7 @@ struct Rpc { | |||
keep_alive: Option<bool>, | |||
experimental_rpcs: Option<bool>, | |||
poll_lifetime: Option<u32>, | |||
jsonrpc_allow_missing_blocks: Option<bool>, |
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.
nit: maybe name this just allow_missing_blocks
? We need the jsonrpc
prefix for args but they're already under the category for configs.
parity/rpc_apis.rs
Outdated
deps.miner.clone(), | ||
$nonces, | ||
deps.gas_price_percentile, | ||
); |
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.
nit: indentation is wrong.
parity/rpc_apis.rs
Outdated
} | ||
} | ||
} | ||
}}; |
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.
nit: this indentation looks weird
Also there's a test failure:
|
block_transaction_count_by_hash block_transaction_count_by_number block_uncles_count_by_hash block_uncles_count_by_number uncle_by_block_hash_and_index uncle_by_block_number_and_index fix PR grumbles
revert config name Co-Authored-By: seunlanlege <[email protected]>
revert cli arg Co-Authored-By: seunlanlege <[email protected]>
revert config name Co-Authored-By: seunlanlege <[email protected]>
rpc/src/v1/impls/eth.rs
Outdated
let best_block = self.client.chain_info().best_block_number; | ||
if let Some(receipt) = self.miner.pending_receipt(best_block, &hash) { | ||
return Box::new(future::ok(Some(receipt.into()))); | ||
match (self.miner.pending_receipt(best_block, &hash), self.options.allow_pending_receipt_query) { |
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.
This will unnecessarily call self.miner.pending_receipt
even when self.options.allow_pending_receipt_query
is false. I would suggest to change it back to the old two if
form.
rpc/src/v1/impls/eth.rs
Outdated
} | ||
|
||
fn transaction_receipt(&self, hash: RpcH256) -> BoxFuture<Option<Receipt>> { | ||
let best_block = self.client.chain_info().best_block_number; |
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.
This is only used inside if self.options.allow_pending_receipt_query {
, so maybe it's better to move it back.
* closes #9188 * check_for_unavailable_block in eth_getTransactionByHash eth_getTransactionByBlockHashAndIndex eth_getTransactionByBlockNumberAndIndex eth_getTransactionReceipt * check for unavailable block in eth_getBlockByNumber * corrected checks for unavailable_block * check for block gaps in db * corrected error messages * corrected error information * added allow-empty-block-result cli flag * address grumbles * --jsonrpc-allow-missing-blocks * fix tests * added checks to block_transaction_count_by_hash block_transaction_count_by_number block_uncles_count_by_hash block_uncles_count_by_number uncle_by_block_hash_and_index uncle_by_block_number_and_index fix PR grumbles * Update parity/cli/mod.rs revert config name Co-Authored-By: seunlanlege <[email protected]> * Update parity/cli/mod.rs revert cli arg Co-Authored-By: seunlanlege <[email protected]> * Apply suggestions from code review revert config name Co-Authored-By: seunlanlege <[email protected]> * fix PR grumbles * fix more PR grumbles
fix #9188