Skip to content
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

Assert height to hash in contains block #19136

Merged
merged 32 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e46b2bc
add assertions
almogdepaz Dec 9, 2024
e06555f
use_height_if_available
almogdepaz Dec 9, 2024
0fcbac1
use try_block_record
almogdepaz Dec 9, 2024
74b27f4
fix recursion
almogdepaz Dec 9, 2024
b229e7e
handle none
almogdepaz Dec 9, 2024
6feaf13
remove assert
almogdepaz Dec 9, 2024
9c1eab1
remove assert
almogdepaz Dec 9, 2024
14c3339
use try in wallet blockchain
almogdepaz Dec 9, 2024
e0cd0cd
fix height o and height to hash in augmented
almogdepaz Dec 23, 2024
fed3e6e
merge main into branch
almogdepaz Dec 24, 2024
31bc5b0
get_correct_block_for_fork
almogdepaz Jan 14, 2025
1437e4e
remove debug code
almogdepaz Jan 14, 2025
4f144a6
use try_block_record
almogdepaz Jan 14, 2025
5a918d7
check main chain againt undelying blockchain
almogdepaz Jan 20, 2025
5cf019f
pass augmented in tests
almogdepaz Jan 20, 2025
4215992
lint
almogdepaz Jan 20, 2025
0ccadb5
revert changes to wallet blockchain
almogdepaz Jan 27, 2025
a48ce05
remove redundant comment
almogdepaz Jan 27, 2025
bf03d6d
lint
almogdepaz Jan 27, 2025
1ab95bc
Merge branch 'main' into assert-height-to-hash-in-contains-block
almogdepaz Jan 27, 2025
8c3271d
remove debug message
almogdepaz Jan 27, 2025
c85adc4
Merge branch 'main' into assert-height-to-hash-in-contains-block
almogdepaz Jan 29, 2025
4533711
revert bad merge
almogdepaz Feb 3, 2025
ec8ef12
make height mandatory
almogdepaz Feb 5, 2025
30d0323
make height mandatory
almogdepaz Feb 5, 2025
cc0fa11
use try_block_record
almogdepaz Feb 6, 2025
c4944a5
fix unfinished test
almogdepaz Feb 6, 2025
bd0caf9
Merge branch 'main' into assert-height-to-hash-in-contains-block
almogdepaz Feb 6, 2025
963d83f
Merge branch 'main' into assert-height-to-hash-in-contains-block
almogdepaz Feb 10, 2025
f1aabee
remove from hh, test contains block
almogdepaz Feb 10, 2025
a3627c6
fix test
almogdepaz Feb 10, 2025
5220666
fix mock and cache
almogdepaz Feb 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion chia/_tests/blockchain/test_augmented_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def height_to_block_record(self, height: uint32) -> BlockRecord:
def height_to_hash(self, height: uint32) -> Optional[bytes32]:
return self.heights.get(height)

def contains_block(self, header_hash: bytes32) -> bool:
def contains_block(self, header_hash: bytes32, height: Optional[uint32] = None) -> bool:
return False # pragma: no cover

def contains_height(self, height: uint32) -> bool:
Expand Down
12 changes: 10 additions & 2 deletions chia/_tests/util/blockchain_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,16 @@ def height_to_hash(self, height: uint32) -> Optional[bytes32]:
assert height in self._height_to_hash
return self._height_to_hash[height]

def contains_block(self, header_hash: bytes32) -> bool:
return header_hash in self._block_records
def contains_block(self, header_hash: bytes32, height: Optional[uint32] = None) -> bool:
if height is None:
block_rec = self.try_block_record(header_hash)
if block_rec is None:
return False
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
return True

async def contains_block_from_db(self, header_hash: bytes32) -> bool:
return header_hash in self._block_records
Expand Down
18 changes: 11 additions & 7 deletions chia/consensus/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -788,12 +788,16 @@ async def validate_unfinished_block(

return PreValidationResult(None, required_iters, conds, uint32(0))

def contains_block(self, header_hash: bytes32) -> 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
def contains_block(self, header_hash: bytes32, height: Optional[uint32] = None) -> bool:
if height is None:
block_rec = self.try_block_record(header_hash)
if block_rec is None:
return False
arvidn marked this conversation as resolved.
Show resolved Hide resolved
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
return True

def block_record(self, header_hash: bytes32) -> BlockRecord:
return self.__block_records[header_hash]
Expand Down Expand Up @@ -955,7 +959,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)
return None

Expand Down
2 changes: 1 addition & 1 deletion chia/consensus/blockchain_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class BlockRecordsProtocol(Protocol):
def try_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]: ...
def block_record(self, header_hash: bytes32) -> BlockRecord: ...
def contains_height(self, height: uint32) -> bool: ...
def contains_block(self, header_hash: bytes32) -> bool: ...
def contains_block(self, header_hash: bytes32, height: Optional[uint32] = None) -> bool: ...
def height_to_hash(self, height: uint32) -> Optional[bytes32]: ...
def height_to_block_record(self, height: uint32) -> BlockRecord: ...

Expand Down
10 changes: 4 additions & 6 deletions chia/consensus/difficulty_adjustment.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,10 @@ def _get_next_sub_slot_iters(
if next_height < constants.EPOCH_BLOCKS:
return uint64(constants.SUB_SLOT_ITERS_STARTING)

if not blocks.contains_block(prev_header_hash):
prev_b = blocks.try_block_record(prev_header_hash)
if prev_b is None:
raise ValueError(f"Header hash {prev_header_hash} not in blocks")

prev_b: BlockRecord = blocks.block_record(prev_header_hash)

# If we are in the same epoch, return same ssi
if not skip_epoch_check:
_, can_finish_epoch = can_finish_sub_and_full_epoch(
Expand Down Expand Up @@ -304,11 +303,10 @@ def _get_next_difficulty(
# We are in the first epoch
return uint64(constants.DIFFICULTY_STARTING)

if not blocks.contains_block(prev_header_hash):
prev_b = blocks.try_block_record(prev_header_hash)
if prev_b is None:
raise ValueError(f"Header hash {prev_header_hash} not in blocks")

prev_b: BlockRecord = blocks.block_record(prev_header_hash)

# If we are in the same slot as previous block, return same difficulty
if not skip_epoch_check:
_, can_finish_epoch = can_finish_sub_and_full_epoch(
Expand Down
3 changes: 2 additions & 1 deletion chia/full_node/full_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ async def short_sync_batch(self, peer: WSChiaConnection, start_height: uint32, t
fork_hash = self.constants.GENESIS_CHALLENGE
assert fork_hash
fork_info = ForkInfo(start_height - 1, start_height - 1, fork_hash)
blockchain = AugmentedBlockchain(self.blockchain)
arvidn marked this conversation as resolved.
Show resolved Hide resolved
for height in range(start_height, target_height, batch_size):
end_height = min(target_height, height + batch_size)
request = RequestBlocks(uint32(height), uint32(end_height), True)
Expand Down Expand Up @@ -757,7 +758,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
Expand Down
3 changes: 1 addition & 2 deletions chia/simulator/add_blocks_in_batches.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,12 @@ async def add_blocks_in_batches(
fork_info = ForkInfo(fork_height, blocks[0].height - 1, peak_hash)

vs = ValidationState(ssi, diff, None)

blockchain = AugmentedBlockchain(full_node.blockchain)
for block_batch in to_batches(blocks, 64):
b = block_batch.entries[0]
if (b.height % 128) == 0:
print(f"main chain: {b.height:4} weight: {b.weight}")
# vs is updated by the call to add_block_batch()
blockchain = AugmentedBlockchain(full_node.blockchain)
success, state_change_summary = await full_node.add_block_batch(
block_batch.entries, PeerInfo("0.0.0.0", 0), fork_info, vs, blockchain
)
Expand Down
21 changes: 15 additions & 6 deletions chia/util/augmented_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ def add_extra_block(self, block: FullBlock, block_record: BlockRecord) -> None:

def remove_extra_block(self, hh: bytes32) -> None:
if hh in self._extra_blocks:
block_record = self._extra_blocks.pop(hh)[1]
del self._height_to_hash[block_record.height]
almogdepaz marked this conversation as resolved.
Show resolved Hide resolved
self._extra_blocks.pop(hh)[1]

# BlocksProtocol
async def lookup_block_generators(self, header_hash: bytes32, generator_refs: set[uint32]) -> dict[uint32, bytes]:
Expand Down Expand Up @@ -82,12 +81,11 @@ async def get_block_record_from_db(self, header_hash: bytes32) -> Optional[Block

def add_block_record(self, block_record: BlockRecord) -> None:
self._underlying.add_block_record(block_record)

self._height_to_hash[block_record.height] = block_record.header_hash
# now that we're adding the block to the underlying blockchain, we don't
# need to keep the extra block around anymore
hh = block_record.header_hash
if hh in self._extra_blocks:
del self._height_to_hash[block_record.height]
del self._extra_blocks[hh]

# BlockRecordsProtocol
Expand All @@ -109,6 +107,7 @@ def height_to_block_record(self, height: uint32) -> BlockRecord:
ret = self._get_block_record(header_hash)
if ret is not None:
return ret
return self._underlying.block_record(header_hash)
arvidn marked this conversation as resolved.
Show resolved Hide resolved
return self._underlying.height_to_block_record(height)

def height_to_hash(self, height: uint32) -> Optional[bytes32]:
Expand All @@ -117,8 +116,18 @@ def height_to_hash(self, height: uint32) -> Optional[bytes32]:
return ret
return self._underlying.height_to_hash(height)

def contains_block(self, header_hash: bytes32) -> bool:
return (header_hash in self._extra_blocks) or self._underlying.contains_block(header_hash)
def contains_block(self, header_hash: bytes32, height: Optional[uint32] = None) -> bool:
if height is None:
block_rec = self.try_block_record(header_hash)
if block_rec is None:
return False
height = block_rec.height
if not self.contains_height(height):
return False
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
return True

def contains_height(self, height: uint32) -> bool:
return (height in self._height_to_hash) or self._underlying.contains_height(height)
Expand Down
12 changes: 10 additions & 2 deletions chia/util/block_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,16 @@ def height_to_hash(self, height: uint32) -> Optional[bytes32]:
return None
return self._height_to_hash[height]

def contains_block(self, header_hash: bytes32) -> bool:
return header_hash in self._block_records
def contains_block(self, header_hash: bytes32, height: Optional[uint32] = None) -> bool:
almogdepaz marked this conversation as resolved.
Show resolved Hide resolved
if height is None:
block_rec = self.try_block_record(header_hash)
if block_rec is None:
return False
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
return True

def contains_height(self, height: uint32) -> bool:
return height in self._height_to_hash
Expand Down
6 changes: 5 additions & 1 deletion chia/wallet/wallet_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,11 @@ async def get_finished_sync_up_to(self) -> uint32:
def get_latest_timestamp(self) -> uint64:
return self._latest_timestamp

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.
"""
arvidn marked this conversation as resolved.
Show resolved Hide resolved
return header_hash in self._block_records

def contains_height(self, height: uint32) -> bool:
Expand Down
Loading