Skip to content

refactor(settings): refactor genesis module #794

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

Merged
merged 1 commit into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 2 additions & 3 deletions hathor/builder/cli_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from hathor.manager import HathorManager
from hathor.p2p.manager import ConnectionsManager
from hathor.p2p.peer_id import PeerId
from hathor.p2p.utils import discover_hostname
from hathor.p2p.utils import discover_hostname, get_genesis_short_hash
from hathor.pubsub import PubSubManager
from hathor.stratum import StratumFactory
from hathor.util import Random, Reactor
Expand Down Expand Up @@ -64,7 +64,6 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
from hathor.p2p.netfilter.utils import add_peer_id_blacklist
from hathor.p2p.peer_discovery import BootstrapPeerDiscovery, DNSPeerDiscovery
from hathor.storage import RocksDBStorage
from hathor.transaction import genesis
from hathor.transaction.storage import (
TransactionCacheStorage,
TransactionMemoryStorage,
Expand All @@ -89,7 +88,7 @@ def create_manager(self, reactor: Reactor) -> HathorManager:
'hathor-core v{hathor}',
hathor=hathor.__version__,
pid=os.getpid(),
genesis=genesis.GENESIS_HASH.hex()[:7],
genesis=get_genesis_short_hash(),
my_peer_id=str(peer_id.id),
python=python,
platform=platform.platform(),
Expand Down
2 changes: 1 addition & 1 deletion hathor/conf/mainnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# Genesis stuff
# output addr: HJB2yxxsHtudGGy3jmVeadwMfRi2zNCKKD
GENESIS_OUTPUT_SCRIPT=bytes.fromhex('76a9147fd4ae0e4fb2d2854e76d359029d8078bb99649e88ac'),
GENESIS_TIMESTAMP=1578075305,
GENESIS_BLOCK_TIMESTAMP=1578075305,
GENESIS_BLOCK_NONCE=2591358,
GENESIS_BLOCK_HASH=bytes.fromhex('000006cb93385b8b87a545a1cbb6197e6caff600c12cc12fc54250d39c8088fc'),
GENESIS_TX1_NONCE=7715,
Expand Down
2 changes: 1 addition & 1 deletion hathor/conf/mainnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ WHITELIST_URL: https://hathor-public-files.s3.amazonaws.com/whitelist_peer_ids

# Genesis stuff
GENESIS_OUTPUT_SCRIPT: 76a9147fd4ae0e4fb2d2854e76d359029d8078bb99649e88ac
GENESIS_TIMESTAMP: 1578075305
GENESIS_BLOCK_TIMESTAMP: 1578075305
GENESIS_BLOCK_NONCE: 2591358
GENESIS_BLOCK_HASH: 000006cb93385b8b87a545a1cbb6197e6caff600c12cc12fc54250d39c8088fc
GENESIS_TX1_NONCE: 7715
Expand Down
15 changes: 14 additions & 1 deletion hathor/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,20 @@ def MAXIMUM_NUMBER_OF_HALVINGS(self) -> int:
GENESIS_OUTPUT_SCRIPT: bytes = bytes.fromhex('76a914a584cf48b161e4a49223ed220df30037ab740e0088ac')

# Genesis timestamps, nonces and hashes
GENESIS_TIMESTAMP: int = 1572636343 # used as is for genesis_block, +1 for genesis_tx1 and +2 for genesis_tx2

# Timestamp used for the genesis block
GENESIS_BLOCK_TIMESTAMP: int = 1572636343

@property
def GENESIS_TX1_TIMESTAMP(self) -> int:
"""Timestamp used for the first genesis transaction."""
return self.GENESIS_BLOCK_TIMESTAMP + 1

@property
def GENESIS_TX2_TIMESTAMP(self) -> int:
"""Timestamp used for the second genesis transaction."""
return self.GENESIS_BLOCK_TIMESTAMP + 2

GENESIS_BLOCK_NONCE: int = 3526202
GENESIS_BLOCK_HASH: bytes = bytes.fromhex('000007eb968a6cdf0499e2d033faf1e163e0dc9cf41876acad4d421836972038')
GENESIS_TX1_NONCE: int = 12595
Expand Down
2 changes: 1 addition & 1 deletion hathor/conf/testnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
BOOTSTRAP_DNS=['golf.testnet.hathor.network'],
# Genesis stuff
GENESIS_OUTPUT_SCRIPT=bytes.fromhex('76a914a584cf48b161e4a49223ed220df30037ab740e0088ac'),
GENESIS_TIMESTAMP=1577836800,
GENESIS_BLOCK_TIMESTAMP=1577836800,
GENESIS_BLOCK_NONCE=826272,
GENESIS_BLOCK_HASH=bytes.fromhex('0000033139d08176d1051fb3a272c3610457f0c7f686afbe0afe3d37f966db85'),
GENESIS_TX1_NONCE=190,
Expand Down
2 changes: 1 addition & 1 deletion hathor/conf/testnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ BOOTSTRAP_DNS:

# Genesis stuff
GENESIS_OUTPUT_SCRIPT: 76a914a584cf48b161e4a49223ed220df30037ab740e0088ac
GENESIS_TIMESTAMP: 1577836800
GENESIS_BLOCK_TIMESTAMP: 1577836800
GENESIS_BLOCK_NONCE: 826272
GENESIS_BLOCK_HASH: 0000033139d08176d1051fb3a272c3610457f0c7f686afbe0afe3d37f966db85
GENESIS_TX1_NONCE: 190
Expand Down
2 changes: 2 additions & 0 deletions hathor/indexes/base_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from structlog import get_logger

from hathor.conf.get_settings import get_settings
from hathor.indexes.scope import Scope
from hathor.transaction.base_transaction import BaseTransaction

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

def init_start(self, indexes_manager: 'IndexesManager') -> None:
Expand Down
11 changes: 7 additions & 4 deletions hathor/indexes/height_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from hathor.indexes.base_index import BaseIndex
from hathor.indexes.scope import Scope
from hathor.transaction import BaseTransaction, Block
from hathor.transaction.genesis import BLOCK_GENESIS
from hathor.types import VertexId
from hathor.util import not_none

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


BLOCK_GENESIS_ENTRY: IndexEntry = IndexEntry(not_none(BLOCK_GENESIS.hash), BLOCK_GENESIS.timestamp)


class _AddToIndexItem(NamedTuple):
height: int
hash: bytes
Expand All @@ -54,6 +50,13 @@ class HeightIndex(BaseIndex):
"""Store the block hash for each given height
"""

def get_genesis_block_entry(self) -> IndexEntry:
"""Return the index entry for the genesis block."""
return IndexEntry(
self._settings.GENESIS_BLOCK_HASH,
self._settings.GENESIS_BLOCK_TIMESTAMP
)

def get_scope(self) -> Scope:
return SCOPE

Expand Down
4 changes: 2 additions & 2 deletions hathor/indexes/memory_height_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from typing import Optional

from hathor.indexes.height_index import BLOCK_GENESIS_ENTRY, HeightIndex, HeightInfo, IndexEntry
from hathor.indexes.height_index import HeightIndex, HeightInfo, IndexEntry


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

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

def _add(self, height: int, block_hash: bytes, timestamp: int, *, can_reorg: bool) -> None:
if len(self._index) < height:
Expand Down
6 changes: 3 additions & 3 deletions hathor/indexes/memory_info_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

class MemoryInfoIndex(InfoIndex):
def __init__(self):
super().__init__()
self._block_count = 0
self._tx_count = 0
self._first_timestamp = 0
Expand All @@ -35,11 +36,10 @@ def get_db_name(self) -> Optional[str]:
return None

def force_clear(self) -> None:
from hathor.transaction.genesis import BLOCK_GENESIS, TX_GENESIS2
self._block_count = 1
self._tx_count = 2
self._first_timestamp = BLOCK_GENESIS.timestamp
self._latest_timestamp = TX_GENESIS2.timestamp
self._first_timestamp = self._settings.GENESIS_BLOCK_TIMESTAMP
self._latest_timestamp = self._settings.GENESIS_TX2_TIMESTAMP

def update_timestamps(self, tx: BaseTransaction) -> None:
if tx.is_genesis:
Expand Down
5 changes: 3 additions & 2 deletions hathor/indexes/rocksdb_height_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from structlog import get_logger

from hathor.indexes.height_index import BLOCK_GENESIS_ENTRY, HeightIndex, HeightInfo, IndexEntry
from hathor.indexes.height_index import HeightIndex, HeightInfo, IndexEntry
from hathor.indexes.rocksdb_utils import RocksDBIndexUtils

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

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

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

def _to_key(self, height: int) -> bytes:
Expand Down
5 changes: 3 additions & 2 deletions hathor/p2p/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from hathor.conf.get_settings import get_settings
from hathor.indexes.height_index import HeightInfo
from hathor.p2p.peer_discovery import DNSPeerDiscovery
from hathor.transaction.genesis import GENESIS_HASH
from hathor.transaction.genesis import get_representation_for_all_genesis


def discover_hostname() -> Optional[str]:
Expand Down Expand Up @@ -75,7 +75,8 @@ def description_to_connection_string(description: str) -> tuple[str, Optional[st
def get_genesis_short_hash() -> str:
""" Return the first 7 chars of the GENESIS_HASH used for validation that the genesis are the same
"""
return GENESIS_HASH.hex()[:7]
settings = get_settings()
return get_representation_for_all_genesis(settings).hex()[:7]


def get_settings_hello_dict() -> dict[str, Any]:
Expand Down
3 changes: 1 addition & 2 deletions hathor/simulator/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from hathor.simulator.clock import HeapClock, MemoryReactorHeapClock
from hathor.simulator.miner.geometric_miner import GeometricMiner
from hathor.simulator.tx_generator import RandomTransactionGenerator
from hathor.transaction.genesis import _get_genesis_transactions_unsafe
from hathor.util import Random
from hathor.wallet import HDWallet

Expand Down Expand Up @@ -128,7 +127,7 @@ def start(self) -> None:
assert not self._started
self._started = True
self._patches_rc_increment()
first_timestamp = min(tx.timestamp for tx in _get_genesis_transactions_unsafe(None))
first_timestamp = self.settings.GENESIS_BLOCK_TIMESTAMP
dt = self.rng.randint(3600, 120 * 24 * 3600)
self._clock.advance(first_timestamp + dt)
self.log.debug('randomized step: clock advance start', dt=dt)
Expand Down
2 changes: 1 addition & 1 deletion hathor/transaction/base_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ def is_genesis(self) -> bool:
if self.hash is None:
return False
from hathor.transaction.genesis import is_genesis
return is_genesis(self.hash)
return is_genesis(self.hash, settings=self._settings)

@abstractmethod
def get_funds_fields_from_struct(self, buf: bytes, *, verbose: VerboseCallback = None) -> bytes:
Expand Down
67 changes: 14 additions & 53 deletions hathor/transaction/genesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,71 +12,32 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING

from hathor.conf import HathorSettings
from hathor.transaction import BaseTransaction, Block, Transaction, TxOutput
from hathor.conf.settings import HathorSettings

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

settings = HathorSettings()

BLOCK_GENESIS = Block(
hash=settings.GENESIS_BLOCK_HASH,
nonce=settings.GENESIS_BLOCK_NONCE,
timestamp=settings.GENESIS_TIMESTAMP,
weight=settings.MIN_BLOCK_WEIGHT,
outputs=[
TxOutput(settings.GENESIS_TOKENS, settings.GENESIS_OUTPUT_SCRIPT),
],
)
def get_all_genesis_hashes(settings: HathorSettings) -> list[bytes]:
"""Return all genesis hashes."""
return [
settings.GENESIS_BLOCK_HASH,
settings.GENESIS_TX1_HASH,
settings.GENESIS_TX2_HASH
]

TX_GENESIS1 = Transaction(
hash=settings.GENESIS_TX1_HASH,
nonce=settings.GENESIS_TX1_NONCE,
timestamp=settings.GENESIS_TIMESTAMP + 1,
weight=settings.MIN_TX_WEIGHT,
)

TX_GENESIS2 = Transaction(
hash=settings.GENESIS_TX2_HASH,
nonce=settings.GENESIS_TX2_NONCE,
timestamp=settings.GENESIS_TIMESTAMP + 2,
weight=settings.MIN_TX_WEIGHT,
)

GENESIS = [BLOCK_GENESIS, TX_GENESIS1, TX_GENESIS2]

GENESIS_HASHES = [settings.GENESIS_BLOCK_HASH, settings.GENESIS_TX1_HASH, settings.GENESIS_TX2_HASH]


def _get_genesis_hash() -> bytes:
def get_representation_for_all_genesis(settings: HathorSettings) -> bytes:
"""Return a single hash representing all genesis vertices."""
import hashlib
h = hashlib.sha256()
for tx in GENESIS:
tx_hash = tx.hash
assert tx_hash is not None
for tx_hash in get_all_genesis_hashes(settings):
h.update(tx_hash)
return h.digest()


GENESIS_HASH = _get_genesis_hash()


def _get_genesis_transactions_unsafe(tx_storage: Optional['TransactionStorage']) -> list[BaseTransaction]:
"""You shouldn't get genesis directly. Please, get it from your storage instead."""
genesis = []
for tx in GENESIS:
tx2 = tx.clone()
tx2.storage = tx_storage
genesis.append(tx2)
return genesis


def is_genesis(hash_bytes: bytes) -> bool:
def is_genesis(hash_bytes: bytes, *, settings: HathorSettings) -> bool:
"""Check whether hash is from a genesis transaction."""
for tx in GENESIS:
if hash_bytes == tx.hash:
return True
return False
return hash_bytes in get_all_genesis_hashes(settings)
Loading