Skip to content

Commit d2ebd45

Browse files
committed
feat(indexes): make sync-v1 indexes optional
1 parent 7c129b6 commit d2ebd45

File tree

3 files changed

+74
-30
lines changed

3 files changed

+74
-30
lines changed

hathor/indexes/manager.py

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,12 @@ class IndexesManager(ABC):
5353
log = get_logger()
5454

5555
info: InfoIndex
56-
all_tips: TipsIndex
57-
block_tips: TipsIndex
58-
tx_tips: TipsIndex
59-
56+
all_tips: Optional[TipsIndex]
57+
block_tips: Optional[TipsIndex]
58+
tx_tips: Optional[TipsIndex]
6059
sorted_all: TimestampIndex
6160
sorted_blocks: TimestampIndex
6261
sorted_txs: TimestampIndex
63-
6462
height: HeightIndex
6563
deps: Optional[DepsIndex]
6664
mempool_tips: Optional[MempoolTipsIndex]
@@ -98,6 +96,11 @@ def iter_all_indexes(self) -> Iterator[BaseIndex]:
9896
self.utxo,
9997
])
10098

99+
@abstractmethod
100+
def enable_tips_indexes(self) -> None:
101+
"""Enable tips indexs. It does nothing if it has already been enabled."""
102+
raise NotImplementedError
103+
101104
@abstractmethod
102105
def enable_address_index(self, pubsub: 'PubSubManager') -> None:
103106
"""Enable address index. It does nothing if it has already been enabled."""
@@ -209,18 +212,21 @@ def add_tx(self, tx: BaseTransaction) -> bool:
209212

210213
# These two calls return False when a transaction changes from
211214
# voided to executed and vice-versa.
212-
r1 = self.all_tips.add_tx(tx)
213-
r2 = self.sorted_all.add_tx(tx)
214-
assert r1 == r2
215+
r1 = self.sorted_all.add_tx(tx)
216+
if self.all_tips is not None:
217+
r2 = self.all_tips.add_tx(tx)
218+
assert r1 == r2
215219

216220
if tx.is_block:
217-
r3 = self.block_tips.add_tx(tx)
218-
r4 = self.sorted_blocks.add_tx(tx)
219-
assert r3 == r4
221+
r3 = self.sorted_blocks.add_tx(tx)
222+
if self.block_tips is not None:
223+
r4 = self.block_tips.add_tx(tx)
224+
assert r3 == r4
220225
else:
221-
r3 = self.tx_tips.add_tx(tx)
222-
r4 = self.sorted_txs.add_tx(tx)
223-
assert r3 == r4
226+
r3 = self.sorted_txs.add_tx(tx)
227+
if self.tx_tips is not None:
228+
r4 = self.tx_tips.add_tx(tx)
229+
assert r3 == r4
224230

225231
if self.addresses:
226232
self.addresses.add_tx(tx)
@@ -250,7 +256,8 @@ def del_tx(self, tx: BaseTransaction, *, remove_all: bool = False, relax_assert:
250256
# We delete from indexes in two cases: (i) mark tx as voided, and (ii) remove tx.
251257
# We only remove tx from all_tips and sorted_all when it is removed from the storage.
252258
# For clarity, when a tx is marked as voided, it is not removed from all_tips and sorted_all.
253-
self.all_tips.del_tx(tx, relax_assert=relax_assert)
259+
if self.all_tips is not None:
260+
self.all_tips.del_tx(tx, relax_assert=relax_assert)
254261
self.sorted_all.del_tx(tx)
255262
if self.addresses:
256263
self.addresses.remove_tx(tx)
@@ -264,11 +271,13 @@ def del_tx(self, tx: BaseTransaction, *, remove_all: bool = False, relax_assert:
264271
self.mempool_tips.update(tx, remove=True)
265272

266273
if tx.is_block:
267-
self.block_tips.del_tx(tx, relax_assert=relax_assert)
268274
self.sorted_blocks.del_tx(tx)
275+
if self.block_tips is not None:
276+
self.block_tips.del_tx(tx, relax_assert=relax_assert)
269277
else:
270-
self.tx_tips.del_tx(tx, relax_assert=relax_assert)
271278
self.sorted_txs.del_tx(tx)
279+
if self.tx_tips is not None:
280+
self.tx_tips.del_tx(tx, relax_assert=relax_assert)
272281

273282
if self.tokens:
274283
self.tokens.del_tx(tx)
@@ -283,12 +292,11 @@ def __init__(self) -> None:
283292
from hathor.indexes.memory_height_index import MemoryHeightIndex
284293
from hathor.indexes.memory_info_index import MemoryInfoIndex
285294
from hathor.indexes.memory_timestamp_index import MemoryTimestampIndex
286-
from hathor.indexes.memory_tips_index import MemoryTipsIndex
287295

288296
self.info = MemoryInfoIndex()
289-
self.all_tips = MemoryTipsIndex(scope_type=TipsScopeType.ALL)
290-
self.block_tips = MemoryTipsIndex(scope_type=TipsScopeType.BLOCKS)
291-
self.tx_tips = MemoryTipsIndex(scope_type=TipsScopeType.TXS)
297+
self.all_tips = None
298+
self.block_tips = None
299+
self.tx_tips = None
292300

293301
self.sorted_all = MemoryTimestampIndex(scope_type=TimestampScopeType.ALL)
294302
self.sorted_blocks = MemoryTimestampIndex(scope_type=TimestampScopeType.BLOCKS)
@@ -304,6 +312,15 @@ def __init__(self) -> None:
304312
# XXX: this has to be at the end of __init__, after everything has been initialized
305313
self.__init_checks__()
306314

315+
def enable_tips_indexes(self) -> None:
316+
from hathor.indexes.memory_tips_index import MemoryTipsIndex
317+
if self.all_tips is None:
318+
self.all_tips = MemoryTipsIndex(scope_type=TipsScopeType.ALL)
319+
if self.block_tips is None:
320+
self.block_tips = MemoryTipsIndex(scope_type=TipsScopeType.BLOCKS)
321+
if self.tx_tips is None:
322+
self.tx_tips = MemoryTipsIndex(scope_type=TipsScopeType.TXS)
323+
307324
def enable_address_index(self, pubsub: 'PubSubManager') -> None:
308325
from hathor.indexes.memory_address_index import MemoryAddressIndex
309326
if self.addresses is None:
@@ -332,7 +349,6 @@ def enable_deps_index(self) -> None:
332349

333350
class RocksDBIndexesManager(IndexesManager):
334351
def __init__(self, db: 'rocksdb.DB') -> None:
335-
from hathor.indexes.partial_rocksdb_tips_index import PartialRocksDBTipsIndex
336352
from hathor.indexes.rocksdb_height_index import RocksDBHeightIndex
337353
from hathor.indexes.rocksdb_info_index import RocksDBInfoIndex
338354
from hathor.indexes.rocksdb_timestamp_index import RocksDBTimestampIndex
@@ -341,9 +357,9 @@ def __init__(self, db: 'rocksdb.DB') -> None:
341357

342358
self.info = RocksDBInfoIndex(self._db)
343359
self.height = RocksDBHeightIndex(self._db)
344-
self.all_tips = PartialRocksDBTipsIndex(self._db, scope_type=TipsScopeType.ALL)
345-
self.block_tips = PartialRocksDBTipsIndex(self._db, scope_type=TipsScopeType.BLOCKS)
346-
self.tx_tips = PartialRocksDBTipsIndex(self._db, scope_type=TipsScopeType.TXS)
360+
self.all_tips = None
361+
self.block_tips = None
362+
self.tx_tips = None
347363

348364
self.sorted_all = RocksDBTimestampIndex(self._db, scope_type=TimestampScopeType.ALL)
349365
self.sorted_blocks = RocksDBTimestampIndex(self._db, scope_type=TimestampScopeType.BLOCKS)
@@ -358,6 +374,15 @@ def __init__(self, db: 'rocksdb.DB') -> None:
358374
# XXX: this has to be at the end of __init__, after everything has been initialized
359375
self.__init_checks__()
360376

377+
def enable_tips_indexes(self) -> None:
378+
from hathor.indexes.partial_rocksdb_tips_index import PartialRocksDBTipsIndex
379+
if self.all_tips is None:
380+
self.all_tips = PartialRocksDBTipsIndex(self._db, scope_type=TipsScopeType.ALL)
381+
if self.block_tips is None:
382+
self.block_tips = PartialRocksDBTipsIndex(self._db, scope_type=TipsScopeType.BLOCKS)
383+
if self.tx_tips is None:
384+
self.tx_tips = PartialRocksDBTipsIndex(self._db, scope_type=TipsScopeType.TXS)
385+
361386
def enable_address_index(self, pubsub: 'PubSubManager') -> None:
362387
from hathor.indexes.rocksdb_address_index import RocksDBAddressIndex
363388
if self.addresses is None:

hathor/manager.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ def __init__(self, reactor: Reactor, *, pubsub: PubSubManager, peer_id: Optional
160160

161161
self._event_manager = event_manager
162162

163+
if enable_sync_v1:
164+
assert self.tx_storage.indexes is not None
165+
self.log.debug('enable sync-v1 indexes')
166+
self.tx_storage.indexes.enable_tips_indexes()
163167
if enable_sync_v2:
164168
assert self.tx_storage.indexes is not None
165169
self.log.debug('enable sync-v2 indexes')

hathor/transaction/storage/transaction_storage.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -528,15 +528,23 @@ def first_timestamp(self) -> int:
528528
raise NotImplementedError
529529

530530
@abstractmethod
531-
def get_best_block_tips(self, timestamp: Optional[float] = None, *, skip_cache: bool = False) -> List[bytes]:
531+
def get_best_block_tips(self, *, skip_cache: bool = False) -> List[bytes]:
532532
""" Return a list of blocks that are heads in a best chain. It must be used when mining.
533533
534534
When more than one block is returned, it means that there are multiple best chains and
535535
you can choose any of them.
536536
"""
537-
if timestamp is None and not skip_cache and self._best_block_tips_cache is not None:
538-
return self._best_block_tips_cache[:]
537+
# ignoring cache because current implementation is ~O(1)
538+
assert self.indexes is not None
539+
return [self.indexes.height.get_tip()]
540+
541+
@abstractmethod
542+
def get_past_best_block_tips(self, timestamp: Optional[float] = None) -> List[bytes]:
543+
""" Return a list of blocks that are heads in a best chain. It must be used when mining.
539544
545+
When more than one block is returned, it means that there are multiple best chains and
546+
you can choose any of them.
547+
"""
540548
best_score = 0.0
541549
best_tip_blocks: List[bytes] = []
542550

@@ -915,6 +923,7 @@ def iter_mempool_tips_from_tx_tips(self) -> Iterator[Transaction]:
915923
This method requires indexes to be enabled.
916924
"""
917925
assert self.indexes is not None
926+
assert self.indexes.tx_tips is not None
918927
tx_tips = self.indexes.tx_tips
919928

920929
for interval in tx_tips[self.latest_timestamp + 1]:
@@ -1019,8 +1028,11 @@ def remove_cache(self) -> None:
10191028
"""Remove all caches in case we don't need it."""
10201029
self.indexes = None
10211030

1022-
def get_best_block_tips(self, timestamp: Optional[float] = None, *, skip_cache: bool = False) -> List[bytes]:
1023-
return super().get_best_block_tips(timestamp, skip_cache=skip_cache)
1031+
def get_best_block_tips(self, *, skip_cache: bool = False) -> List[bytes]:
1032+
return super().get_best_block_tips(skip_cache=skip_cache)
1033+
1034+
def get_past_best_block_tips(self, timestamp: Optional[float] = None) -> List[bytes]:
1035+
return super().get_past_best_block_tips(timestamp)
10241036

10251037
def get_weight_best_block(self) -> float:
10261038
return super().get_weight_best_block()
@@ -1029,6 +1041,7 @@ def get_block_tips(self, timestamp: Optional[float] = None) -> Set[Interval]:
10291041
if self.indexes is None:
10301042
raise NotImplementedError
10311043
assert self.indexes is not None
1044+
assert self.indexes.block_tips is not None
10321045
if timestamp is None:
10331046
timestamp = self.latest_timestamp
10341047
return self.indexes.block_tips[timestamp]
@@ -1037,6 +1050,7 @@ def get_tx_tips(self, timestamp: Optional[float] = None) -> Set[Interval]:
10371050
if self.indexes is None:
10381051
raise NotImplementedError
10391052
assert self.indexes is not None
1053+
assert self.indexes.tx_tips is not None
10401054
if timestamp is None:
10411055
timestamp = self.latest_timestamp
10421056
tips = self.indexes.tx_tips[timestamp]
@@ -1054,6 +1068,7 @@ def get_all_tips(self, timestamp: Optional[float] = None) -> Set[Interval]:
10541068
if self.indexes is None:
10551069
raise NotImplementedError
10561070
assert self.indexes is not None
1071+
assert self.indexes.all_tips is not None
10571072
if timestamp is None:
10581073
timestamp = self.latest_timestamp
10591074

0 commit comments

Comments
 (0)