|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
3 | 3 | from collections.abc import Collection
|
4 |
| -from contextlib import AbstractAsyncContextManager |
5 | 4 | from typing import Optional, Protocol
|
6 | 5 |
|
7 |
| -import aiosqlite |
8 | 6 | from chia_rs import BlockRecord, FullBlock, SubEpochChallengeSegment, SubEpochSummary
|
9 | 7 | from chia_rs.sized_bytes import bytes32
|
10 | 8 | from chia_rs.sized_ints import uint32, uint64
|
|
13 | 11 | from chia.types.coin_record import CoinRecord
|
14 | 12 |
|
15 | 13 |
|
| 14 | +class ConsensusStoreWriteProtocol(Protocol): |
| 15 | + """ |
| 16 | + Protocol for performing mutating operations on the consensus store. |
| 17 | +
|
| 18 | + Instances implementing this protocol should be acquired via the async |
| 19 | + context manager on ConsensusStoreProtocol to ensure atomic write |
| 20 | + operations (e.g., wrapping all writes in a single DB transaction). |
| 21 | + """ |
| 22 | + |
| 23 | + # Block store writes |
| 24 | + async def add_full_block(self, header_hash: bytes32, block: FullBlock, block_record: BlockRecord) -> None: ... |
| 25 | + def rollback_cache_block(self, header_hash: bytes32) -> None: ... |
| 26 | + async def rollback(self, height: int) -> None: ... |
| 27 | + async def set_in_chain(self, header_hashes: list[tuple[bytes32]]) -> None: ... |
| 28 | + async def set_peak(self, header_hash: bytes32) -> None: ... |
| 29 | + async def persist_sub_epoch_challenge_segments( |
| 30 | + self, ses_block_hash: bytes32, segments: list[SubEpochChallengeSegment] |
| 31 | + ) -> None: ... |
| 32 | + |
| 33 | + # Coin store writes |
| 34 | + async def rollback_to_block(self, block_index: int) -> dict[bytes32, CoinRecord]: ... |
| 35 | + async def new_block( |
| 36 | + self, |
| 37 | + height: uint32, |
| 38 | + timestamp: uint64, |
| 39 | + included_reward_coins: Collection[Coin], |
| 40 | + tx_additions: Collection[tuple[bytes32, Coin, bool]], |
| 41 | + tx_removals: list[bytes32], |
| 42 | + ) -> None: ... |
| 43 | + |
| 44 | + |
16 | 45 | class ConsensusStoreProtocol(Protocol):
|
17 | 46 | """
|
18 |
| - Protocol for the consensus store, which provides methods to interact with |
19 |
| - the consensus-related data in the blockchain. |
| 47 | + Read-only protocol for the consensus store. |
| 48 | +
|
| 49 | + This protocol also acts as an async context manager. Entering the context |
| 50 | + yields a ConsensusStoreWriteProtocol instance, which must be used for |
| 51 | + performing write (mutating) operations. This ensures atomic writes and |
| 52 | + makes it harder to accidentally perform writes outside a transaction. |
| 53 | +
|
| 54 | + Example usage: |
| 55 | + async with store as writer: |
| 56 | + await writer.add_full_block(...) |
| 57 | + await writer.set_peak(...) |
| 58 | +
|
| 59 | + # Outside the context, only read methods are available |
| 60 | + br = await store.get_block_record(header_hash) |
20 | 61 | """
|
21 | 62 |
|
22 |
| - # Block store methods |
23 |
| - def transaction(self) -> AbstractAsyncContextManager[aiosqlite.Connection]: ... |
| 63 | + # Async context manager methods |
| 64 | + async def __aenter__(self) -> ConsensusStoreWriteProtocol: ... |
| 65 | + async def __aexit__(self, exc_type, exc, tb) -> Optional[bool]: ... |
24 | 66 |
|
| 67 | + # Block store reads |
25 | 68 | async def get_block_records_close_to_peak(
|
26 | 69 | self, blocks_n: int
|
27 | 70 | ) -> tuple[dict[bytes32, BlockRecord], Optional[bytes32]]: ...
|
28 | 71 | async def get_full_block(self, header_hash: bytes32) -> Optional[FullBlock]: ...
|
29 |
| - async def add_full_block(self, header_hash: bytes32, block: FullBlock, block_record: BlockRecord) -> None: ... |
30 |
| - def rollback_cache_block(self, header_hash: bytes32) -> None: ... |
31 | 72 | async def get_block_records_by_hash(self, header_hashes: list[bytes32]) -> list[BlockRecord]: ...
|
32 |
| - async def rollback(self, height: int) -> None: ... |
33 |
| - async def set_in_chain(self, header_hashes: list[tuple[bytes32]]) -> None: ... |
34 |
| - async def set_peak(self, header_hash: bytes32) -> None: ... |
35 | 73 | async def get_block_records_in_range(self, start: int, stop: int) -> dict[bytes32, BlockRecord]: ...
|
36 | 74 | def get_block_from_cache(self, header_hash: bytes32) -> Optional[FullBlock]: ...
|
37 | 75 | async def get_blocks_by_hash(self, header_hashes: list[bytes32]) -> list[FullBlock]: ...
|
38 | 76 | async def get_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]: ...
|
39 | 77 | async def get_prev_hash(self, header_hash: bytes32) -> bytes32: ...
|
40 |
| - async def persist_sub_epoch_challenge_segments( |
41 |
| - self, ses_block_hash: bytes32, segments: list[SubEpochChallengeSegment] |
42 |
| - ) -> None: ... |
43 | 78 | async def get_sub_epoch_challenge_segments(
|
44 | 79 | self, ses_block_hash: bytes32
|
45 | 80 | ) -> Optional[list[SubEpochChallengeSegment]]: ...
|
46 | 81 | async def get_generator(self, header_hash: bytes32) -> Optional[bytes]: ...
|
47 | 82 | async def get_generators_at(self, heights: set[uint32]) -> dict[uint32, bytes]: ...
|
48 | 83 |
|
49 |
| - # Coin store methods |
| 84 | + # Coin store reads |
50 | 85 | async def get_coin_records(self, names: Collection[bytes32]) -> list[CoinRecord]: ...
|
51 |
| - async def rollback_to_block(self, block_index: int) -> dict[bytes32, CoinRecord]: ... |
52 |
| - async def new_block( |
53 |
| - self, |
54 |
| - height: uint32, |
55 |
| - timestamp: uint64, |
56 |
| - included_reward_coins: Collection[Coin], |
57 |
| - tx_additions: Collection[tuple[bytes32, Coin, bool]], |
58 |
| - tx_removals: list[bytes32], |
59 |
| - ) -> None: ... |
60 | 86 | async def get_coins_added_at_height(self, height: uint32) -> list[CoinRecord]: ...
|
61 | 87 | async def get_coins_removed_at_height(self, height: uint32) -> list[CoinRecord]: ...
|
62 | 88 |
|
63 |
| - # Height map methods |
| 89 | + # Height map methods (kept here for now; non-async and maybe_flush remain on read protocol) |
64 | 90 | def get_ses_heights(self) -> list[uint32]: ...
|
65 | 91 | def get_ses(self, height: uint32) -> SubEpochSummary: ...
|
66 | 92 | def contains_height(self, height: uint32) -> bool: ...
|
|
0 commit comments