Example #1
0
 def _manager_kwargs(self):
     peer_id = PeerId()
     network = 'testnet'
     wallet = self._create_test_wallet()
     tx_storage = getattr(self, 'tx_storage', None)
     if tx_storage is None:
         if self.use_memory_storage:
             from hathor.transaction.storage.memory_storage import TransactionMemoryStorage
             tx_storage = TransactionMemoryStorage()
         else:
             from hathor.transaction.storage.rocksdb_storage import TransactionRocksDBStorage
             directory = tempfile.mkdtemp()
             self.tmpdirs.append(directory)
             tx_storage = TransactionRocksDBStorage(directory)
     assert (
         hasattr(self, '_enable_sync_v1') and
         hasattr(self, '_enable_sync_v2') and
         (self._enable_sync_v1 or self._enable_sync_v2)
     ), (
         'Please set both `_enable_sync_v1` and `_enable_sync_v2` on the class. '
         'Also they can\'t both be False. '
         'This is by design so we don\'t forget to test for multiple sync versions.'
     )
     return dict(
         peer_id=peer_id,
         network=network,
         wallet=wallet,
         tx_storage=tx_storage,
         wallet_index=True,
         enable_sync_v1=self._enable_sync_v1,
         enable_sync_v2=self._enable_sync_v2,
     )
Example #2
0
    def create_peer(self, network: Optional[str] = None, peer_id: Optional[PeerId] = None,
                    enable_sync_v1: bool = True, enable_sync_v2: bool = True,
                    soft_voided_tx_ids: Optional[Set[bytes]] = None) -> HathorManager:
        assert self._started
        if network is None:
            network = self._network

        wallet = HDWallet(gap_limit=2)
        wallet._manually_initialize()

        assert peer_id is not None  # XXX: temporary, for checking that tests are using the peer_id
        if peer_id is None:
            peer_id = PeerId()
        tx_storage = TransactionMemoryStorage()
        manager = HathorManager(
            self._clock,
            peer_id=peer_id,
            network=network,
            wallet=wallet,
            enable_sync_v1=enable_sync_v1,
            enable_sync_v2=enable_sync_v2,
            tx_storage=tx_storage,
            rng=Random(self.rng.getrandbits(64)),
            soft_voided_tx_ids=soft_voided_tx_ids,
        )

        manager.reactor = self._clock
        manager._full_verification = True
        manager.start()
        self.run_to_completion()

        # Don't use it anywhere else. It is unsafe to generate mnemonic words like this.
        # It should be used only for testing purposes.
        m = Mnemonic('english')
        words = m.to_mnemonic(self.rng.randbytes(32))
        self.log.debug('randomized step: generate wallet', words=words)
        wallet.unlock(words=words, tx_storage=manager.tx_storage)
        return manager
Example #3
0
    def __init__(
        self,
        pubsub: PubSubManager,
        avg_time_between_blocks: int,
        tx_storage: Optional[TransactionStorage] = None,
        reactor: Optional[IReactorCore] = None,
    ):
        """
        :param pubsub: If not given, a new one is created.
        :param tx_storage: If not given, a new one is created.
        :param avg_time_between_blocks: Seconds between blocks (comes from manager)
        :param tx_storage: Transaction storage
        :param reactor: Twisted reactor that handles the time and callLater
        """
        # Transactions count in the network
        self.transactions = 0

        # Blocks count in the network
        self.blocks = 0

        # Height of the best chain of the network
        self.best_block_height = 0

        # Hash rate of the network
        self.hash_rate = 0.0

        # Peers connected
        self.peers = 0

        # Hash rate of tx
        self.tx_hash_rate = 0.0

        # Hash rate of block
        self.block_hash_rate = 0

        # Length of the tx deque
        self.weight_tx_deque_len = 60

        # Length of the block deque
        self.weight_block_deque_len = 450

        # Stores caculated tx weights saved in tx storage
        self.weight_tx_deque = deque(maxlen=self.weight_tx_deque_len)

        # Stores caculated block weights saved in tx storage
        self.weight_block_deque = deque(maxlen=self.weight_block_deque_len)

        self.avg_time_between_blocks = avg_time_between_blocks

        self.pubsub = pubsub

        self.tx_storage = tx_storage or TransactionMemoryStorage()

        if reactor is None:
            from twisted.internet import reactor as twisted_reactor
            reactor = twisted_reactor
        self.reactor = reactor

        # If metric capture data is running
        self.is_running = False

        # Coefficient of exponential calculus
        self.exponential_alfa = 0.7

        # Time between method call to store hash count
        self.tx_hash_store_interval = 1
        self.block_hash_store_interval = 1

        # Websocket data stored
        self.websocket_connections = 0
        self.subscribed_addresses = 0

        # Websocket factory
        self.websocket_factory = None

        # weight of the head of the best blockchain
        self.best_block_weight = 0

        # Stratum data
        self.completed_jobs = 0
        self.blocks_found = 0
        self.estimated_hash_rate = 0

        # Stratum factory
        self.stratum_factory = None

        # Send-token timeouts counter
        self.send_token_timeouts = 0

        # Time between method call to collect data
        self.collect_data_interval = settings.METRICS_COLLECT_DATA_INTERVAL

        # A timer to periodically collect data
        self._lc_collect_data = LoopingCall(self._collect_data)
        self._lc_collect_data.clock = reactor
Example #4
0
    def __init__(self,
                 reactor: IReactorCore,
                 peer_id: Optional[PeerId] = None,
                 network: Optional[str] = None,
                 hostname: Optional[str] = None,
                 pubsub: Optional[PubSubManager] = None,
                 wallet: Optional[BaseWallet] = None,
                 tx_storage: Optional[TransactionStorage] = None,
                 peer_storage: Optional[Any] = None,
                 default_port: int = 40403,
                 wallet_index: bool = False,
                 stratum_port: Optional[int] = None,
                 min_block_weight: Optional[int] = None,
                 ssl: bool = True) -> None:
        """
        :param reactor: Twisted reactor which handles the mainloop and the events.
        :param peer_id: Id of this node. If not given, a new one is created.
        :param network: Name of the network this node participates. Usually it is either testnet or mainnet.
        :type network: string

        :param hostname: The hostname of this node. It is used to generate its entrypoints.
        :type hostname: string

        :param pubsub: If not given, a new one is created.
        :type pubsub: :py:class:`hathor.pubsub.PubSubManager`

        :param tx_storage: If not given, a :py:class:`TransactionMemoryStorage` one is created.
        :type tx_storage: :py:class:`hathor.transaction.storage.transaction_storage.TransactionStorage`

        :param peer_storage: If not given, a new one is created.
        :type peer_storage: :py:class:`hathor.p2p.peer_storage.PeerStorage`

        :param default_port: Network default port. It is used when only ip addresses are discovered.
        :type default_port: int

        :param wallet_index: If should add a wallet index in the storage
        :type wallet_index: bool

        :param stratum_port: Stratum server port. Stratum server will only be created if it is not None.
        :type stratum_port: Optional[int]

        :param min_block_weight: Minimum weight for blocks.
        :type min_block_weight: Optional[int]
        """
        from hathor.p2p.factory import HathorServerFactory, HathorClientFactory
        from hathor.p2p.manager import ConnectionsManager
        from hathor.transaction.storage.memory_storage import TransactionMemoryStorage
        from hathor.metrics import Metrics

        self.log = logger.new()

        self.reactor = reactor
        if hasattr(self.reactor, 'addSystemEventTrigger'):
            self.reactor.addSystemEventTrigger('after', 'shutdown', self.stop)

        self.state: Optional[HathorManager.NodeState] = None
        self.profiler: Optional[Any] = None

        # Hostname, used to be accessed by other peers.
        self.hostname = hostname

        # Remote address, which can be different from local address.
        self.remote_address = None

        self.my_peer = peer_id or PeerId()
        self.network = network or 'testnet'

        # XXX Should we use a singleton or a new PeerStorage? [msbrogli 2018-08-29]
        self.pubsub = pubsub or PubSubManager(self.reactor)
        self.tx_storage = tx_storage or TransactionMemoryStorage()
        self.tx_storage.pubsub = self.pubsub
        if wallet_index and self.tx_storage.with_index:
            self.tx_storage.wallet_index = WalletIndex(self.pubsub)
            self.tx_storage.tokens_index = TokensIndex()

        self.avg_time_between_blocks = settings.AVG_TIME_BETWEEN_BLOCKS
        self.min_block_weight = min_block_weight or settings.MIN_BLOCK_WEIGHT
        self.min_tx_weight = settings.MIN_TX_WEIGHT

        self.metrics = Metrics(
            pubsub=self.pubsub,
            avg_time_between_blocks=self.avg_time_between_blocks,
            tx_storage=tx_storage,
            reactor=self.reactor,
        )

        self.consensus_algorithm = ConsensusAlgorithm()

        self.peer_discoveries: List[PeerDiscovery] = []

        self.ssl = ssl
        self.server_factory = HathorServerFactory(self.network,
                                                  self.my_peer,
                                                  node=self,
                                                  use_ssl=ssl)
        self.client_factory = HathorClientFactory(self.network,
                                                  self.my_peer,
                                                  node=self,
                                                  use_ssl=ssl)
        self.connections = ConnectionsManager(self.reactor, self.my_peer,
                                              self.server_factory,
                                              self.client_factory, self.pubsub,
                                              self, ssl)

        self.wallet = wallet
        if self.wallet:
            self.wallet.pubsub = self.pubsub
            self.wallet.reactor = self.reactor

        # When manager is in test mode we reduce the weight of blocks/transactions.
        self.test_mode: int = 0

        # Multiplier coefficient to adjust the minimum weight of a normal tx to 18
        self.min_tx_weight_coefficient = 1.6
        # Amount in which tx min weight reaches the middle point between the minimum and maximum weight.
        self.min_tx_weight_k = 100

        self.stratum_factory = StratumFactory(
            manager=self, port=stratum_port) if stratum_port else None
        # Set stratum factory for metrics object
        self.metrics.stratum_factory = self.stratum_factory

        self._allow_mining_without_peers = False

        # Thread pool used to resolve pow when sending tokens
        self.pow_thread_pool = ThreadPool(minthreads=0,
                                          maxthreads=settings.MAX_POW_THREADS,
                                          name='Pow thread pool')

        # List of addresses to listen for new connections (eg: [tcp:8000])
        self.listen_addresses: List[str] = []
Example #5
0
    def create_peer(self,
                    network,
                    peer_id=None,
                    wallet=None,
                    tx_storage=None,
                    unlock_wallet=True,
                    wallet_index=False,
                    capabilities=None,
                    full_verification=True,
                    enable_sync_v1=None,
                    enable_sync_v2=None,
                    checkpoints=None):
        if enable_sync_v1 is None:
            assert hasattr(self, '_enable_sync_v1'), (
                '`_enable_sync_v1` has no default by design, either set one on '
                'the test class or pass `enable_sync_v1` by argument')
            enable_sync_v1 = self._enable_sync_v1
        if enable_sync_v2 is None:
            assert hasattr(self, '_enable_sync_v2'), (
                '`_enable_sync_v2` has no default by design, either set one on '
                'the test class or pass `enable_sync_v2` by argument')
            enable_sync_v2 = self._enable_sync_v2
        assert enable_sync_v1 or enable_sync_v2, 'enable at least one sync version'

        if peer_id is None:
            peer_id = PeerId()
        if not wallet:
            wallet = self._create_test_wallet()
            if unlock_wallet:
                wallet.unlock(b'MYPASS')
        if tx_storage is None:
            if self.use_memory_storage:
                from hathor.transaction.storage.memory_storage import TransactionMemoryStorage
                tx_storage = TransactionMemoryStorage()
            else:
                from hathor.transaction.storage.rocksdb_storage import TransactionRocksDBStorage
                directory = tempfile.mkdtemp()
                self.tmpdirs.append(directory)
                tx_storage = TransactionRocksDBStorage(directory)
        manager = HathorManager(
            self.clock,
            peer_id=peer_id,
            network=network,
            wallet=wallet,
            tx_storage=tx_storage,
            wallet_index=wallet_index,
            capabilities=capabilities,
            rng=self.rng,
            enable_sync_v1=enable_sync_v1,
            enable_sync_v2=enable_sync_v2,
            checkpoints=checkpoints,
        )

        # XXX: just making sure that tests set this up correctly
        if enable_sync_v2:
            assert SyncVersion.V2 in manager.connections._sync_factories
        else:
            assert SyncVersion.V2 not in manager.connections._sync_factories
        if enable_sync_v1:
            assert SyncVersion.V1 in manager.connections._sync_factories
        else:
            assert SyncVersion.V1 not in manager.connections._sync_factories

        manager.avg_time_between_blocks = 0.0001
        manager._full_verification = full_verification
        manager.start()
        self.run_to_completion()
        return manager