Skip to content

Commit cac84b5

Browse files
richardkissarvidn
andauthored
Simplify BlockStore (#19880)
* Simplify `BlockStore` * Update chia/full_node/block_store.py Co-authored-by: Arvid Norberg <[email protected]> --------- Co-authored-by: Arvid Norberg <[email protected]>
1 parent 91ca11a commit cac84b5

File tree

6 files changed

+34
-44
lines changed

6 files changed

+34
-44
lines changed

chia/_tests/blockchain/blockchain_test_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ async def check_block_store_invariant(bc: Blockchain):
2222

2323
in_chain = set()
2424
max_height = -1
25-
async with db_wrapper.writer_maybe_transaction() as conn:
25+
async with bc.block_store.transaction() as conn:
2626
async with conn.execute("SELECT height, in_main_chain FROM full_blocks") as cursor:
2727
rows = await cursor.fetchall()
2828
for row in rows:

chia/_tests/blockchain/test_blockchain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3647,7 +3647,7 @@ async def test_get_blocks_at(self, empty_blockchain: Blockchain, default_1000_bl
36473647
heights.append(block.height)
36483648
await _validate_and_add_block(b, block)
36493649

3650-
blocks = await b.get_block_records_at(heights, batch_size=2)
3650+
blocks = await b.get_block_records_at(heights)
36513651
assert blocks
36523652
assert len(blocks) == 200
36533653
assert blocks[-1].height == 199

chia/consensus/blockchain.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ async def add_block(
421421

422422
try:
423423
# Always add the block to the database
424-
async with self.block_store.db_wrapper.writer():
424+
async with self.block_store.transaction():
425425
# Perform the DB operations to update the state, and rollback if something goes wrong
426426
await self.block_store.add_full_block(header_hash, block, block_record)
427427
records, state_change_summary = await self._reconsider_peak(block_record, genesis, fork_info)
@@ -883,7 +883,7 @@ async def get_header_blocks_in_range(
883883

884884
blocks: list[FullBlock] = []
885885
for hash in hashes.copy():
886-
block = self.block_store.block_cache.get(hash)
886+
block = self.block_store.get_block_from_cache(hash)
887887
if block is not None:
888888
blocks.append(block)
889889
hashes.remove(hash)
@@ -926,27 +926,18 @@ async def get_header_block_by_height(
926926
return None
927927
return header_dict[header_hash]
928928

929-
async def get_block_records_at(self, heights: list[uint32], batch_size: int = 900) -> list[BlockRecord]:
929+
async def get_block_records_at(self, heights: list[uint32]) -> list[BlockRecord]:
930930
"""
931931
gets block records by height (only blocks that are part of the chain)
932932
"""
933-
records: list[BlockRecord] = []
934933
hashes: list[bytes32] = []
935-
assert batch_size < self.block_store.db_wrapper.host_parameter_limit
936934
for height in heights:
937935
header_hash: Optional[bytes32] = self.height_to_hash(height)
938936
if header_hash is None:
939937
raise ValueError(f"Do not have block at height {height}")
940938
hashes.append(header_hash)
941-
if len(hashes) > batch_size:
942-
res = await self.block_store.get_block_records_by_hash(hashes)
943-
records.extend(res)
944-
hashes = []
945-
946-
if len(hashes) > 0:
947-
res = await self.block_store.get_block_records_by_hash(hashes)
948-
records.extend(res)
949-
return records
939+
940+
return await self.block_store.get_block_records_by_hash(hashes)
950941

951942
def try_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]:
952943
if header_hash in self.__block_records:

chia/full_node/block_store.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33
import dataclasses
44
import logging
55
import sqlite3
6+
from contextlib import AbstractAsyncContextManager
67
from typing import Optional
78

9+
import aiosqlite
810
import typing_extensions
911
import zstd
1012
from chia_rs import BlockRecord, FullBlock, SubEpochChallengeSegment, SubEpochSegments
1113
from chia_rs.sized_bytes import bytes32
1214
from chia_rs.sized_ints import uint32
1315

1416
from chia.full_node.full_block_utils import GeneratorBlockInfo, block_info_from_block, generator_from_block
17+
from chia.util.batches import to_batches
1518
from chia.util.db_wrapper import DBWrapper2, execute_fetchone
1619
from chia.util.errors import Err
1720
from chia.util.lru_cache import LRUCache
@@ -189,6 +192,12 @@ async def get_sub_epoch_challenge_segments(
189192
return challenge_segments
190193
return None
191194

195+
def transaction(self) -> AbstractAsyncContextManager[aiosqlite.Connection]:
196+
return self.db_wrapper.writer()
197+
198+
def get_block_from_cache(self, header_hash: bytes32) -> Optional[FullBlock]:
199+
return self.block_cache.get(header_hash)
200+
192201
def rollback_cache_block(self, header_hash: bytes32) -> None:
193202
try:
194203
self.block_cache.remove(header_hash)
@@ -322,20 +331,21 @@ async def get_block_records_by_hash(self, header_hashes: list[bytes32]) -> list[
322331
Returns a list of Block Records, ordered by the same order in which header_hashes are passed in.
323332
Throws an exception if the blocks are not present
324333
"""
334+
325335
if len(header_hashes) == 0:
326336
return []
327337

328338
all_blocks: dict[bytes32, BlockRecord] = {}
329-
async with self.db_wrapper.reader_no_transaction() as conn:
330-
async with conn.execute(
331-
"SELECT header_hash,block_record "
332-
"FROM full_blocks "
333-
f"WHERE header_hash in ({'?,' * (len(header_hashes) - 1)}?)",
334-
header_hashes,
335-
) as cursor:
336-
for row in await cursor.fetchall():
337-
block_rec = BlockRecord.from_bytes(row[1])
338-
all_blocks[block_rec.header_hash] = block_rec
339+
for batch in to_batches(header_hashes, self.db_wrapper.host_parameter_limit):
340+
async with self.db_wrapper.reader_no_transaction() as conn:
341+
async with conn.execute(
342+
"SELECT header_hash,block_record FROM full_blocks "
343+
f"WHERE header_hash in ({'?,' * (len(batch.entries) - 1)}?)",
344+
batch.entries,
345+
) as cursor:
346+
for row in await cursor.fetchall():
347+
block_rec = BlockRecord.from_bytes(row[1])
348+
all_blocks[block_rec.header_hash] = block_rec
339349

340350
ret: list[BlockRecord] = []
341351
for hh in header_hashes:

chia/full_node/full_node_api.py

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,24 +1453,13 @@ async def request_block_headers(self, request: wallet_protocol.RequestBlockHeade
14531453

14541454
if request.end_height < request.start_height or request.end_height - request.start_height > 128:
14551455
return make_msg(ProtocolMessageTypes.reject_block_headers, reject)
1456-
if self.full_node.block_store.db_wrapper.db_version == 2:
1457-
try:
1458-
blocks_bytes = await self.full_node.block_store.get_block_bytes_in_range(
1459-
request.start_height, request.end_height
1460-
)
1461-
except ValueError:
1462-
return make_msg(ProtocolMessageTypes.reject_block_headers, reject)
1463-
1464-
else:
1465-
height_to_hash = self.full_node.blockchain.height_to_hash
1466-
header_hashes: list[bytes32] = []
1467-
for i in range(request.start_height, request.end_height + 1):
1468-
header_hash: Optional[bytes32] = height_to_hash(uint32(i))
1469-
if header_hash is None:
1470-
return make_msg(ProtocolMessageTypes.reject_header_blocks, reject)
1471-
header_hashes.append(header_hash)
1456+
try:
1457+
blocks_bytes = await self.full_node.block_store.get_block_bytes_in_range(
1458+
request.start_height, request.end_height
1459+
)
1460+
except ValueError:
1461+
return make_msg(ProtocolMessageTypes.reject_block_headers, reject)
14721462

1473-
blocks_bytes = await self.full_node.block_store.get_block_bytes_by_hash(header_hashes)
14741463
if len(blocks_bytes) != (request.end_height - request.start_height + 1): # +1 because interval is inclusive
14751464
return make_msg(ProtocolMessageTypes.reject_block_headers, reject)
14761465
return_filter = request.return_filter

chia/simulator/full_node_simulator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ async def revert_block_height(self, new_height: uint32) -> None:
167167
raise ValueError("Cannot revert to a height less than 1.")
168168
block_record: BlockRecord = self.full_node.blockchain.height_to_block_record(new_height)
169169
# remove enough data to allow a bunch of blocks to be wiped.
170-
async with self.full_node.block_store.db_wrapper.writer():
170+
async with self.full_node.block_store.transaction():
171171
# set coinstore
172172
await self.full_node.coin_store.rollback_to_block(new_height)
173173
# set blockstore to new height

0 commit comments

Comments
 (0)