Skip to content

Commit 870ee5e

Browse files
committed
refactor(settings): refactor genesis module
1 parent 274bb12 commit 870ee5e

19 files changed

+116
-100
lines changed

hathor/builder/cli_builder.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from hathor.manager import HathorManager
3232
from hathor.p2p.manager import ConnectionsManager
3333
from hathor.p2p.peer_id import PeerId
34-
from hathor.p2p.utils import discover_hostname
34+
from hathor.p2p.utils import discover_hostname, get_genesis_short_hash
3535
from hathor.pubsub import PubSubManager
3636
from hathor.stratum import StratumFactory
3737
from hathor.util import Random, Reactor
@@ -64,7 +64,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
6464
from hathor.p2p.netfilter.utils import add_peer_id_blacklist
6565
from hathor.p2p.peer_discovery import BootstrapPeerDiscovery, DNSPeerDiscovery
6666
from hathor.storage import RocksDBStorage
67-
from hathor.transaction import genesis
6867
from hathor.transaction.storage import (
6968
TransactionCacheStorage,
7069
TransactionMemoryStorage,
@@ -89,7 +88,7 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
8988
'hathor-core v{hathor}',
9089
hathor=hathor.__version__,
9190
pid=os.getpid(),
92-
genesis=genesis.GENESIS_HASH.hex()[:7],
91+
genesis=get_genesis_short_hash(),
9392
my_peer_id=str(peer_id.id),
9493
python=python,
9594
platform=platform.platform(),

hathor/indexes/base_index.py

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from structlog import get_logger
1919

20+
from hathor.conf.get_settings import get_settings
2021
from hathor.indexes.scope import Scope
2122
from hathor.transaction.base_transaction import BaseTransaction
2223

@@ -33,6 +34,7 @@ class BaseIndex(ABC):
3334
created to generalize how we initialize indexes and keep track of which ones are up-to-date.
3435
"""
3536
def __init__(self) -> None:
37+
self._settings = get_settings()
3638
self.log = logger.new()
3739

3840
def init_start(self, indexes_manager: 'IndexesManager') -> None:

hathor/indexes/height_index.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from hathor.indexes.base_index import BaseIndex
1919
from hathor.indexes.scope import Scope
2020
from hathor.transaction import BaseTransaction, Block
21-
from hathor.transaction.genesis import BLOCK_GENESIS
2221
from hathor.types import VertexId
2322
from hathor.util import not_none
2423

@@ -41,9 +40,6 @@ class HeightInfo(NamedTuple):
4140
id: VertexId
4241

4342

44-
BLOCK_GENESIS_ENTRY: IndexEntry = IndexEntry(not_none(BLOCK_GENESIS.hash), BLOCK_GENESIS.timestamp)
45-
46-
4743
class _AddToIndexItem(NamedTuple):
4844
height: int
4945
hash: bytes
@@ -54,6 +50,13 @@ class HeightIndex(BaseIndex):
5450
"""Store the block hash for each given height
5551
"""
5652

53+
def get_genesis_block_entry(self) -> IndexEntry:
54+
"""Return the index entry for the genesis block."""
55+
return IndexEntry(
56+
self._settings.GENESIS_BLOCK_HASH,
57+
self._settings.GENESIS_TIMESTAMP
58+
)
59+
5760
def get_scope(self) -> Scope:
5861
return SCOPE
5962

hathor/indexes/memory_height_index.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from typing import Optional
1616

17-
from hathor.indexes.height_index import BLOCK_GENESIS_ENTRY, HeightIndex, HeightInfo, IndexEntry
17+
from hathor.indexes.height_index import HeightIndex, HeightInfo, IndexEntry
1818

1919

2020
class MemoryHeightIndex(HeightIndex):
@@ -31,7 +31,7 @@ def get_db_name(self) -> Optional[str]:
3131
return None
3232

3333
def force_clear(self) -> None:
34-
self._index = [BLOCK_GENESIS_ENTRY]
34+
self._index = [self.get_genesis_block_entry()]
3535

3636
def _add(self, height: int, block_hash: bytes, timestamp: int, *, can_reorg: bool) -> None:
3737
if len(self._index) < height:

hathor/indexes/memory_info_index.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
class MemoryInfoIndex(InfoIndex):
2525
def __init__(self):
26+
super().__init__()
2627
self._block_count = 0
2728
self._tx_count = 0
2829
self._first_timestamp = 0
@@ -35,11 +36,11 @@ def get_db_name(self) -> Optional[str]:
3536
return None
3637

3738
def force_clear(self) -> None:
38-
from hathor.transaction.genesis import BLOCK_GENESIS, TX_GENESIS2
39+
from hathor.transaction.genesis import get_genesis_block, get_genesis_tx2
3940
self._block_count = 1
4041
self._tx_count = 2
41-
self._first_timestamp = BLOCK_GENESIS.timestamp
42-
self._latest_timestamp = TX_GENESIS2.timestamp
42+
self._first_timestamp = get_genesis_block(self._settings).timestamp
43+
self._latest_timestamp = get_genesis_tx2(self._settings).timestamp
4344

4445
def update_timestamps(self, tx: BaseTransaction) -> None:
4546
if tx.is_genesis:

hathor/indexes/rocksdb_height_index.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from structlog import get_logger
1818

19-
from hathor.indexes.height_index import BLOCK_GENESIS_ENTRY, HeightIndex, HeightInfo, IndexEntry
19+
from hathor.indexes.height_index import HeightIndex, HeightInfo, IndexEntry
2020
from hathor.indexes.rocksdb_utils import RocksDBIndexUtils
2121

2222
if TYPE_CHECKING: # pragma: no cover
@@ -44,6 +44,7 @@ class RocksDBHeightIndex(HeightIndex, RocksDBIndexUtils):
4444

4545
def __init__(self, db: 'rocksdb.DB', *, cf_name: Optional[bytes] = None) -> None:
4646
self.log = logger.new()
47+
HeightIndex.__init__(self)
4748
RocksDBIndexUtils.__init__(self, db, cf_name or _CF_NAME_HEIGHT_INDEX)
4849

4950
def get_db_name(self) -> Optional[str]:
@@ -56,7 +57,7 @@ def force_clear(self) -> None:
5657
def _init_db(self) -> None:
5758
""" Initialize the database with the genesis entry."""
5859
key_genesis = self._to_key(0)
59-
value_genesis = self._to_value(BLOCK_GENESIS_ENTRY)
60+
value_genesis = self._to_value(self.get_genesis_block_entry())
6061
self._db.put((self._cf, key_genesis), value_genesis)
6162

6263
def _to_key(self, height: int) -> bytes:

hathor/p2p/utils.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from hathor.conf.get_settings import get_settings
3232
from hathor.indexes.height_index import HeightInfo
3333
from hathor.p2p.peer_discovery import DNSPeerDiscovery
34-
from hathor.transaction.genesis import GENESIS_HASH
34+
from hathor.transaction.genesis import get_genesis_hash
3535

3636

3737
def discover_hostname() -> Optional[str]:
@@ -75,7 +75,8 @@ def description_to_connection_string(description: str) -> tuple[str, Optional[st
7575
def get_genesis_short_hash() -> str:
7676
""" Return the first 7 chars of the GENESIS_HASH used for validation that the genesis are the same
7777
"""
78-
return GENESIS_HASH.hex()[:7]
78+
settings = get_settings()
79+
return get_genesis_hash(settings).hex()[:7]
7980

8081

8182
def get_settings_hello_dict() -> dict[str, Any]:

hathor/simulator/simulator.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
from hathor.simulator.clock import HeapClock, MemoryReactorHeapClock
2929
from hathor.simulator.miner.geometric_miner import GeometricMiner
3030
from hathor.simulator.tx_generator import RandomTransactionGenerator
31-
from hathor.transaction.genesis import _get_genesis_transactions_unsafe
3231
from hathor.util import Random
3332
from hathor.wallet import HDWallet
3433

@@ -128,7 +127,7 @@ def start(self) -> None:
128127
assert not self._started
129128
self._started = True
130129
self._patches_rc_increment()
131-
first_timestamp = min(tx.timestamp for tx in _get_genesis_transactions_unsafe(None))
130+
first_timestamp = self.settings.GENESIS_TIMESTAMP
132131
dt = self.rng.randint(3600, 120 * 24 * 3600)
133132
self._clock.advance(first_timestamp + dt)
134133
self.log.debug('randomized step: clock advance start', dt=dt)

hathor/transaction/base_transaction.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ def is_genesis(self) -> bool:
357357
if self.hash is None:
358358
return False
359359
from hathor.transaction.genesis import is_genesis
360-
return is_genesis(self.hash)
360+
return is_genesis(self.hash, settings=self._settings)
361361

362362
@abstractmethod
363363
def get_funds_fields_from_struct(self, buf: bytes, *, verbose: VerboseCallback = None) -> bytes:

hathor/transaction/genesis.py

+58-54
Original file line numberDiff line numberDiff line change
@@ -12,71 +12,75 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from typing import TYPE_CHECKING, Optional
15+
from typing import TYPE_CHECKING
1616

17-
from hathor.conf import HathorSettings
17+
from hathor.conf.settings import HathorSettings
1818
from hathor.transaction import BaseTransaction, Block, Transaction, TxOutput
1919

2020
if TYPE_CHECKING:
2121
from hathor.transaction.storage import TransactionStorage # noqa: F401
2222

23-
settings = HathorSettings()
2423

25-
BLOCK_GENESIS = Block(
26-
hash=settings.GENESIS_BLOCK_HASH,
27-
nonce=settings.GENESIS_BLOCK_NONCE,
28-
timestamp=settings.GENESIS_TIMESTAMP,
29-
weight=settings.MIN_BLOCK_WEIGHT,
30-
outputs=[
31-
TxOutput(settings.GENESIS_TOKENS, settings.GENESIS_OUTPUT_SCRIPT),
32-
],
33-
)
34-
35-
TX_GENESIS1 = Transaction(
36-
hash=settings.GENESIS_TX1_HASH,
37-
nonce=settings.GENESIS_TX1_NONCE,
38-
timestamp=settings.GENESIS_TIMESTAMP + 1,
39-
weight=settings.MIN_TX_WEIGHT,
40-
)
41-
42-
TX_GENESIS2 = Transaction(
43-
hash=settings.GENESIS_TX2_HASH,
44-
nonce=settings.GENESIS_TX2_NONCE,
45-
timestamp=settings.GENESIS_TIMESTAMP + 2,
46-
weight=settings.MIN_TX_WEIGHT,
47-
)
48-
49-
GENESIS = [BLOCK_GENESIS, TX_GENESIS1, TX_GENESIS2]
50-
51-
GENESIS_HASHES = [settings.GENESIS_BLOCK_HASH, settings.GENESIS_TX1_HASH, settings.GENESIS_TX2_HASH]
52-
53-
54-
def _get_genesis_hash() -> bytes:
24+
def get_genesis_block(settings: HathorSettings) -> Block:
25+
"""Return the genesis block."""
26+
return Block(
27+
hash=settings.GENESIS_BLOCK_HASH,
28+
nonce=settings.GENESIS_BLOCK_NONCE,
29+
timestamp=settings.GENESIS_TIMESTAMP,
30+
weight=settings.MIN_BLOCK_WEIGHT,
31+
outputs=[
32+
TxOutput(settings.GENESIS_TOKENS, settings.GENESIS_OUTPUT_SCRIPT),
33+
],
34+
)
35+
36+
37+
def get_genesis_tx1(settings: HathorSettings) -> Transaction:
38+
"""Return the genesis tx1."""
39+
return Transaction(
40+
hash=settings.GENESIS_TX1_HASH,
41+
nonce=settings.GENESIS_TX1_NONCE,
42+
timestamp=settings.GENESIS_TIMESTAMP + 1,
43+
weight=settings.MIN_TX_WEIGHT,
44+
)
45+
46+
47+
def get_genesis_tx2(settings: HathorSettings) -> Transaction:
48+
"""Return the genesis tx2."""
49+
return Transaction(
50+
hash=settings.GENESIS_TX2_HASH,
51+
nonce=settings.GENESIS_TX2_NONCE,
52+
timestamp=settings.GENESIS_TIMESTAMP + 2,
53+
weight=settings.MIN_TX_WEIGHT,
54+
)
55+
56+
57+
def get_all_genesis(settings: HathorSettings) -> list[BaseTransaction]:
58+
"""Return all genesis vertices."""
59+
return [
60+
get_genesis_block(settings),
61+
get_genesis_tx1(settings),
62+
get_genesis_tx2(settings)
63+
]
64+
65+
66+
def get_all_genesis_hashes(settings: HathorSettings) -> list[bytes]:
67+
"""Return all genesis hashes."""
68+
return [
69+
settings.GENESIS_BLOCK_HASH,
70+
settings.GENESIS_TX1_HASH,
71+
settings.GENESIS_TX2_HASH
72+
]
73+
74+
75+
def get_genesis_hash(settings: HathorSettings) -> bytes:
76+
"""Return a single hash representing all genesis."""
5577
import hashlib
5678
h = hashlib.sha256()
57-
for tx in GENESIS:
58-
tx_hash = tx.hash
59-
assert tx_hash is not None
79+
for tx_hash in get_all_genesis_hashes(settings):
6080
h.update(tx_hash)
6181
return h.digest()
6282

6383

64-
GENESIS_HASH = _get_genesis_hash()
65-
66-
67-
def _get_genesis_transactions_unsafe(tx_storage: Optional['TransactionStorage']) -> list[BaseTransaction]:
68-
"""You shouldn't get genesis directly. Please, get it from your storage instead."""
69-
genesis = []
70-
for tx in GENESIS:
71-
tx2 = tx.clone()
72-
tx2.storage = tx_storage
73-
genesis.append(tx2)
74-
return genesis
75-
76-
77-
def is_genesis(hash_bytes: bytes) -> bool:
84+
def is_genesis(hash_bytes: bytes, *, settings: HathorSettings) -> bool:
7885
"""Check whether hash is from a genesis transaction."""
79-
for tx in GENESIS:
80-
if hash_bytes == tx.hash:
81-
return True
82-
return False
86+
return hash_bytes in get_all_genesis_hashes(settings)

hathor/transaction/storage/transaction_storage.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,11 @@ def _save_or_verify_genesis(self) -> None:
320320

321321
def _get_genesis_from_settings(self) -> list[BaseTransaction]:
322322
"""Return all genesis from settings."""
323-
from hathor.transaction.genesis import _get_genesis_transactions_unsafe
324-
return _get_genesis_transactions_unsafe(self)
323+
from hathor.transaction.genesis import get_all_genesis
324+
all_genesis = get_all_genesis(self._settings)
325+
for tx in all_genesis:
326+
tx.storage = self
327+
return all_genesis
325328

326329
def _save_to_weakref(self, tx: BaseTransaction) -> None:
327330
""" Save transaction to weakref.

hathor/transaction/transaction_metadata.py

+6-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from collections import defaultdict
1616
from typing import TYPE_CHECKING, Any, Optional
1717

18+
from hathor.conf.get_settings import get_settings
1819
from hathor.feature_activation.feature import Feature
1920
from hathor.feature_activation.model.feature_state import FeatureState
2021
from hathor.transaction.validation_state import ValidationState
@@ -127,8 +128,10 @@ def __init__(
127128

128129
self.feature_activation_bit_counts = feature_activation_bit_counts
129130

131+
settings = get_settings()
132+
130133
# Genesis specific:
131-
if hash is not None and is_genesis(hash):
134+
if hash is not None and is_genesis(hash, settings=settings):
132135
self.validation = ValidationState.FULL
133136

134137
def get_tx(self) -> 'BaseTransaction':
@@ -248,10 +251,8 @@ def to_json_extended(self, tx_storage: 'TransactionStorage') -> dict[str, Any]:
248251

249252
@classmethod
250253
def create_from_json(cls, data: dict[str, Any]) -> 'TransactionMetadata':
251-
from hathor.transaction.genesis import is_genesis
252-
253-
meta = cls()
254-
meta.hash = bytes.fromhex(data['hash']) if data['hash'] else None
254+
hash_ = bytes.fromhex(data['hash']) if data['hash'] else None
255+
meta = cls(hash=hash_)
255256
for idx, hashes in data['spent_outputs']:
256257
for h_hex in hashes:
257258
meta.spent_outputs[idx].append(bytes.fromhex(h_hex))
@@ -293,9 +294,6 @@ def create_from_json(cls, data: dict[str, Any]) -> 'TransactionMetadata':
293294
_val_name = data.get('validation', None)
294295
meta.validation = ValidationState.from_name(_val_name) if _val_name is not None else ValidationState.INITIAL
295296

296-
if meta.hash is not None and is_genesis(meta.hash):
297-
meta.validation = ValidationState.FULL
298-
299297
return meta
300298

301299
def clone(self) -> 'TransactionMetadata':

tests/p2p/test_split_brain.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ class BaseHathorSyncMethodsTestCase(unittest.TestCase):
1414

1515
def setUp(self):
1616
super().setUp()
17-
from hathor.transaction.genesis import _get_genesis_transactions_unsafe
1817

19-
first_timestamp = min(tx.timestamp for tx in _get_genesis_transactions_unsafe(None))
18+
first_timestamp = self._settings.GENESIS_TIMESTAMP
2019
self.clock.advance(first_timestamp + self.rng.randint(3600, 120*24*3600))
2120

2221
self.network = 'testnet'

tests/resources/wallet/test_thin_wallet.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ def test_error_request(self):
275275

276276
resource = SendTokensResource(self.manager)
277277
request = TestDummyRequest('POST', 'thin_wallet/send_tokens', {})
278-
dummy_tx = genesis.BLOCK_GENESIS
278+
dummy_tx = genesis.get_genesis_block(self._settings)
279279

280280
self.assertIsNotNone(request._finishedDeferreds)
281281
resource._err_tx_resolve('Error', _Context(tx=dummy_tx, request=request), 'error')

0 commit comments

Comments
 (0)