-
Notifications
You must be signed in to change notification settings - Fork 2k
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
add assertions to contains block #19001
Changes from all commits
e46b2bc
e06555f
0fcbac1
74b27f4
b229e7e
6feaf13
9c1eab1
14c3339
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -769,12 +769,20 @@ async def validate_unfinished_block( | |
|
||
return PreValidationResult(None, required_iters, conds, uint32(0)) | ||
|
||
def contains_block(self, header_hash: bytes32) -> bool: | ||
def contains_block(self, header_hash: bytes32, height: Optional[uint32] = None) -> bool: | ||
""" | ||
True if we have already added this block to the chain. This may return false for orphan blocks | ||
that we have added but no longer keep in memory. | ||
""" | ||
return header_hash in self.__block_records | ||
if height is None: | ||
block_rec = self.try_block_record(header_hash) | ||
if block_rec is None: | ||
return False | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we also return false for blocks that are part of the main chain, but no longer in the cache. |
||
height = block_rec.height | ||
block_hash_from_hh = self.height_to_hash(height) | ||
if block_hash_from_hh is None or block_hash_from_hh != header_hash: | ||
return False | ||
Comment on lines
+783
to
+784
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not convinced this was the intention of this function, or rather, that it is the expectation of callers. I think the block being in the cache is one of the expectations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this doesn't really make sense to me in the case of the short_sync methods or even for add block |
||
return True | ||
|
||
def block_record(self, header_hash: bytes32) -> BlockRecord: | ||
return self.__block_records[header_hash] | ||
|
@@ -932,7 +940,7 @@ async def get_block_records_at(self, heights: list[uint32], batch_size: int = 90 | |
return records | ||
|
||
def try_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]: | ||
if self.contains_block(header_hash): | ||
if header_hash in self.__block_records: | ||
return self.block_record(header_hash) | ||
Comment on lines
+943
to
944
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it seems a bit backwards to make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i dont have a strong opinion on that, if we do it the other way around we need to throw an explicit exception for when we dont have the block |
||
return None | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -595,7 +595,7 @@ async def short_sync_batch(self, peer: WSChiaConnection, start_height: uint32, t | |
self.sync_store.batch_syncing.remove(peer.peer_node_id) | ||
self.log.error(f"Error short batch syncing, could not fetch block at height {start_height}") | ||
return False | ||
if not self.blockchain.contains_block(first.block.prev_header_hash): | ||
if not self.blockchain.contains_block(first.block.prev_header_hash, first.block.height - 1): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here, we're not really asking whether the blocks i part of the main chain, we're asking if its in the block cache. if it isn't, we declare this a deep reorg or catch-up (and presumably transition to long-sync). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i disagree, for short_sync_batch we assume we are syncing from start_height where start_height - 1 is in our chain so checking if first -1 is in the main chain is correct this is only done for the first_block.prev_header_hash which is expected to be the fork point i.e in out chain There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, I guess we expect both in this case. |
||
self.log.info("Batch syncing stopped, this is a deep chain") | ||
self.sync_store.batch_syncing.remove(peer.peer_node_id) | ||
# First sb not connected to our blockchain, do a long sync instead | ||
|
@@ -699,7 +699,10 @@ async def short_sync_backtrack( | |
f"Failed to fetch block {curr_height} from {peer.get_peer_logging()}, wrong type {type(curr)}" | ||
) | ||
blocks.append(curr.block) | ||
if self.blockchain.contains_block(curr.block.prev_header_hash) or curr_height == 0: | ||
if ( | ||
self.blockchain.contains_block(curr.block.prev_header_hash, curr.block.height - 1) | ||
or curr_height == 0 | ||
): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that this call site is not concerned with whether the block is in the cache or not |
||
found_fork_point = True | ||
break | ||
curr_height -= 1 | ||
|
@@ -748,7 +751,7 @@ async def new_peak(self, request: full_node_protocol.NewPeak, peer: WSChiaConnec | |
# Store this peak/peer combination in case we want to sync to it, and to keep track of peers | ||
self.sync_store.peer_has_block(request.header_hash, peer.peer_node_id, request.weight, request.height, True) | ||
|
||
if self.blockchain.contains_block(request.header_hash): | ||
if self.blockchain.contains_block(request.header_hash, request.height): | ||
return None | ||
|
||
# Not interested in less heavy peaks | ||
|
@@ -2006,7 +2009,7 @@ async def add_block( | |
|
||
# Adds the block to seen, and check if it's seen before (which means header is in memory) | ||
header_hash = block.header_hash | ||
if self.blockchain.contains_block(header_hash): | ||
if self.blockchain.contains_block(header_hash, block.height): | ||
return None | ||
|
||
pre_validation_result: Optional[PreValidationResult] = None | ||
|
@@ -2078,7 +2081,7 @@ async def add_block( | |
enable_profiler(self.profile_block_validation) as pr, | ||
): | ||
# After acquiring the lock, check again, because another asyncio thread might have added it | ||
if self.blockchain.contains_block(header_hash): | ||
if self.blockchain.contains_block(header_hash, block.height): | ||
return None | ||
validation_start = time.monotonic() | ||
# Tries to add the block to the blockchain, if we already validated transactions, don't do it again | ||
|
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 comment should be updated to say that it will return false for orphan blocks. I take the current "may" to mean that orphan blocks are less likely to be in the cache.
This function also always returned false for blocks that aren't in the cache, regardless of whether they're in the main chain or not. The comment should say this too.
The new
height
parameter isn't really explained either. I assume it adds an extra check; not only thatheader_hash
is in the main chain and in the cache, but also that it has the specified height.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 hight is an optimization for most cases where we now the hight of the block (the only case we dont is unfinished blocks)
i agree with all your points, im still trying to figure out exactly what the correct Behavior is supposed to be but im pretty sure the current state is incorect for both short_sync_backtrack and short_sync_batch