-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Conversation
Implement fix for missing blocks due to suspected bug when block_hash(id) returned None, latest_block was still set at id. Also implement validity check of reported hashes (in case of re-org) and re-set last_block to the last block reported that is still valid. Add const to set history size for validity check.
It looks like @mattrutherford signed our Contributor License Agreement. 👍 Many thanks, Parity Technologies CLA Bot |
rpc/src/v1/tests/mocked/eth.rs
Outdated
// in the case of a re-org we get same block number if hash is different - BlockId::Number(2) | ||
tester.client.blocks.write().remove(&hash2).unwrap(); | ||
tester.client.numbers.write().remove(&2).unwrap(); | ||
tester.client.numbers.write().insert(1, hash2); |
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 that this line is actually changing hash of block1, why isn't that block part of the response?
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.
Good catch, that would be the case if the hash was different, but actually in import_block()
in test_client.rs
, that value gets overwritten again by the old hash! So I just need to take that line out because it effectively does nothing.
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 current implementation LGTM, but I think we could also implement this by just storing (last_reported_number, last_reported_hash)
. We can calculate the tree_route
between the current best block and the last reported block. If there's no re-org then last_reported_hash
is an ancestor of best_block_hash
, so tree_route(last, best).ancestor == last
(and index should be 0). If there was a re-org then tree route will get us the common ancestor between the forks and we need to push to the client the route from common ancestor until best block. There's also the case where tree_route
might return None
if one of the provided hashes doesn't exist in the db, I'm not sure what to do in this case (just send everything from last_reported_block_number
until best_block_number
? Or from last_reported_block_number - 32
?).
OK, thanks for the comments @andresilva . I like the elegant solution you mentioned, but depends in practice on how often a re-org would exceed 1 block; and if so whether duplicating returned hashes would be less less nice from an end-user perspective? Personally I think on balance I would prefer to keep as it is, but I am open to re-working it, if it's deemed the additional overhead is undesirable? |
@mattrutherford I think assuming re-orgs are smaller than 32 blocks both methods would return the same results, the common ancestor found by |
OK, noted, thanks. I notice that tree_root also includes forked blocks so we'd need to remove those if we care about duplication of the returned hashes. |
Ah, I see what you mean, indeed if there was a re-org |
I guess we could also rename |
Thanks a lot guys, this is great! |
Fixes: #9858
Implement validity check of reported hashes (in case of re-org)
to determine the last block reported that is still valid. This will return hashes for
block numbers that have previously been reported if the hash is different.
Add const to set history length for validity check. Currently set to 32 blocks.