def test_create_from_json(self): p1 = PeerId() data1 = p1.to_json(include_private_key=True) p2 = PeerId.create_from_json(data1) data2 = p2.to_json(include_private_key=True) self.assertEqual(data1, data2) p2.validate()
def test_create_from_json_without_private_key(self): p1 = PeerId() data1 = p1.to_json() # Just to test a part of the code del data1['entrypoints'] p2 = PeerId.create_from_json(data1) data2 = p2.to_json() self.assertEqual(data2['entrypoints'], []) data1['entrypoints'] = [] self.assertEqual(data1, data2) p2.validate()
def handle_peers(self, payload: str) -> None: """ Executed when a PEERS command is received. It updates the list of known peers (and tries to connect to new ones). """ received_peers = json.loads(payload) for data in received_peers: peer = PeerId.create_from_json(data) peer.validate() if self.protocol.connections: self.protocol.connections.on_receive_peer(peer, origin=self) remote = self.protocol.transport.getPeer() self.log.debug('received peers', remote=remote, payload=payload)
def handle_peer_id(self, payload: str) -> Generator[Any, Any, None]: """ Executed when a PEER-ID is received. It basically checks the identity of the peer. Only after this step, the peer connection is considered established and ready to communicate. """ protocol = self.protocol data = json.loads(payload) peer = PeerId.create_from_json(data) peer.validate() assert peer.id is not None # If the connection URL had a peer-id parameter we need to check it's the same if protocol.expected_peer_id and peer.id != protocol.expected_peer_id: protocol.send_error_and_close_connection( 'Peer id different from the requested one.') return # is it on the whitelist? if settings.ENABLE_PEER_WHITELIST and peer.id not in protocol.node.peers_whitelist: protocol.send_error_and_close_connection( 'Blocked. Get in touch with Hathor team.') return if peer.id == protocol.my_peer.id: protocol.send_error_and_close_connection('Are you my clone?!') return if protocol.connections: if protocol.connections.is_peer_connected(peer.id): protocol.send_error_and_close_connection( 'We are already connected.') return entrypoint_valid = yield peer.validate_entrypoint(protocol) if not entrypoint_valid: protocol.send_error_and_close_connection( 'Connection string is not in the entrypoints.') return if protocol.use_ssl: certificate_valid = peer.validate_certificate(protocol) if not certificate_valid: protocol.send_error_and_close_connection( 'Public keys from peer and certificate are not the same.') return # If it gets here, the peer is validated, and we are ready to start communicating. protocol.peer = peer self.send_ready()
def prepare(self, args: Namespace) -> None: import hathor from hathor.conf import HathorSettings from hathor.manager import HathorManager, TestMode from hathor.p2p.peer_discovery import BootstrapPeerDiscovery, DNSPeerDiscovery from hathor.p2p.peer_id import PeerId from hathor.p2p.utils import discover_hostname from hathor.transaction import genesis from hathor.transaction.storage import ( TransactionStorage, TransactionCacheStorage, TransactionCompactStorage, TransactionMemoryStorage, ) from hathor.wallet import HDWallet, Wallet settings = HathorSettings() if args.recursion_limit: sys.setrecursionlimit(args.recursion_limit) if not args.peer: peer_id = PeerId() else: data = json.load(open(args.peer, 'r')) peer_id = PeerId.create_from_json(data) print('Hathor v{} (genesis {})'.format(hathor.__version__, genesis.GENESIS_HASH.hex()[:7])) print('My peer id is', peer_id.id) def create_wallet(): if args.wallet == 'hd': print('Using HDWallet') kwargs = { 'words': args.words, } if args.passphrase: wallet_passphrase = getpass.getpass( prompt='HD Wallet passphrase:') kwargs['passphrase'] = wallet_passphrase.encode() if args.data: kwargs['directory'] = args.data return HDWallet(**kwargs) elif args.wallet == 'keypair': print('Using KeyPairWallet') if args.data: wallet = Wallet(directory=args.data) else: wallet = Wallet() wallet.flush_to_disk_interval = 5 # seconds if args.unlock_wallet: wallet_passwd = getpass.getpass(prompt='Wallet password:'******'Invalid type for wallet') tx_storage: TransactionStorage if args.data: wallet_dir = args.data print('Using Wallet at {}'.format(wallet_dir)) if args.rocksdb_storage: from hathor.transaction.storage import TransactionRocksDBStorage tx_dir = os.path.join(args.data, 'tx.db') tx_storage = TransactionRocksDBStorage( path=tx_dir, with_index=(not args.cache)) print('Using TransactionRocksDBStorage at {}'.format(tx_dir)) else: tx_dir = os.path.join(args.data, 'tx') tx_storage = TransactionCompactStorage( path=tx_dir, with_index=(not args.cache)) print('Using TransactionCompactStorage at {}'.format(tx_dir)) if args.cache: tx_storage = TransactionCacheStorage(tx_storage, reactor) if args.cache_size: tx_storage.capacity = args.cache_size if args.cache_interval: tx_storage.interval = args.cache_interval print( 'Using TransactionCacheStorage, capacity {}, interval {}s'. format(tx_storage.capacity, tx_storage.interval)) tx_storage.start() else: # if using MemoryStorage, no need to have cache tx_storage = TransactionMemoryStorage() print('Using TransactionMemoryStorage') self.tx_storage = tx_storage if args.wallet: self.wallet = create_wallet() else: self.wallet = None if args.hostname and args.auto_hostname: print('You cannot use --hostname and --auto-hostname together.') sys.exit(-1) if not args.auto_hostname: hostname = args.hostname else: print('Trying to discover your hostname...') hostname = discover_hostname() if not hostname: print('Aborting because we could not discover your hostname.') print('Try again or run without --auto-hostname.') sys.exit(-1) print('Hostname discovered and set to {}'.format(hostname)) network = settings.NETWORK_NAME self.manager = HathorManager(reactor, peer_id=peer_id, network=network, hostname=hostname, tx_storage=self.tx_storage, wallet=self.wallet, wallet_index=args.wallet_index, stratum_port=args.stratum, min_block_weight=args.min_block_weight, ssl=True) if args.allow_mining_without_peers: self.manager.allow_mining_without_peers() dns_hosts = [] if settings.BOOTSTRAP_DNS: dns_hosts.extend(settings.BOOTSTRAP_DNS) if args.dns: dns_hosts.extend(args.dns) if dns_hosts: self.manager.add_peer_discovery(DNSPeerDiscovery(dns_hosts)) if args.bootstrap: self.manager.add_peer_discovery( BootstrapPeerDiscovery(args.bootstrap)) if args.test_mode_tx_weight: self.manager.test_mode = TestMode.TEST_TX_WEIGHT if self.wallet: self.wallet.test_mode = True for description in args.listen: self.manager.add_listen_address(description) self.start_manager() self.register_resources(args)
def prepare(self, args: Namespace) -> None: import hathor from hathor.cli.util import check_or_exit from hathor.conf import HathorSettings from hathor.conf.get_settings import get_settings_module from hathor.daa import TestMode, _set_test_mode from hathor.manager import HathorManager from hathor.p2p.peer_discovery import BootstrapPeerDiscovery, DNSPeerDiscovery from hathor.p2p.peer_id import PeerId from hathor.p2p.utils import discover_hostname from hathor.transaction import genesis from hathor.transaction.storage import ( TransactionCacheStorage, TransactionCompactStorage, TransactionMemoryStorage, TransactionRocksDBStorage, TransactionStorage, ) from hathor.wallet import HDWallet, Wallet settings = HathorSettings() settings_module = get_settings_module() # only used for logging its location self.log = logger.new() from setproctitle import setproctitle setproctitle('{}hathor-core'.format(args.procname_prefix)) if args.recursion_limit: sys.setrecursionlimit(args.recursion_limit) else: sys.setrecursionlimit(5000) try: import resource except ModuleNotFoundError: pass else: (nofile_soft, _) = resource.getrlimit(resource.RLIMIT_NOFILE) if nofile_soft < 256: print('Maximum number of open file descriptors is too low. Minimum required is 256.') sys.exit(-2) if not args.peer: peer_id = PeerId() else: data = json.load(open(args.peer, 'r')) peer_id = PeerId.create_from_json(data) python = f'{platform.python_version()}-{platform.python_implementation()}' self.check_unsafe_arguments(args) self.log.info( 'hathor-core v{hathor}', hathor=hathor.__version__, pid=os.getpid(), genesis=genesis.GENESIS_HASH.hex()[:7], my_peer_id=str(peer_id.id), python=python, platform=platform.platform(), settings=settings_module.__file__, ) def create_wallet(): if args.wallet == 'hd': kwargs = { 'words': args.words, } if args.passphrase: wallet_passphrase = getpass.getpass(prompt='HD Wallet passphrase:') kwargs['passphrase'] = wallet_passphrase.encode() if args.data: kwargs['directory'] = args.data return HDWallet(**kwargs) elif args.wallet == 'keypair': print('Using KeyPairWallet') if args.data: wallet = Wallet(directory=args.data) else: wallet = Wallet() wallet.flush_to_disk_interval = 5 # seconds if args.unlock_wallet: wallet_passwd = getpass.getpass(prompt='Wallet password:'******'Invalid type for wallet') tx_storage: TransactionStorage if args.memory_storage: check_or_exit(not args.data, '--data should not be used with --memory-storage') # if using MemoryStorage, no need to have cache tx_storage = TransactionMemoryStorage() assert not args.x_rocksdb_indexes, 'RocksDB indexes require RocksDB data' self.log.info('with storage', storage_class=type(tx_storage).__name__) elif args.json_storage: check_or_exit(args.data, '--data is expected') assert not args.x_rocksdb_indexes, 'RocksDB indexes require RocksDB data' tx_storage = TransactionCompactStorage(path=args.data, with_index=(not args.cache)) else: check_or_exit(args.data, '--data is expected') if args.rocksdb_storage: self.log.warn('--rocksdb-storage is now implied, no need to specify it') cache_capacity = args.rocksdb_cache use_memory_indexes = not args.x_rocksdb_indexes tx_storage = TransactionRocksDBStorage(path=args.data, with_index=(not args.cache), cache_capacity=cache_capacity, use_memory_indexes=use_memory_indexes) self.log.info('with storage', storage_class=type(tx_storage).__name__, path=args.data) if args.cache: check_or_exit(not args.memory_storage, '--cache should not be used with --memory-storage') tx_storage = TransactionCacheStorage(tx_storage, reactor) if args.cache_size: tx_storage.capacity = args.cache_size if args.cache_interval: tx_storage.interval = args.cache_interval self.log.info('with cache', capacity=tx_storage.capacity, interval=tx_storage.interval) self.tx_storage = tx_storage self.log.info('with indexes', indexes_class=type(tx_storage.indexes).__name__) if args.wallet: self.wallet = create_wallet() self.log.info('with wallet', wallet=self.wallet, path=args.data) else: self.wallet = None if args.hostname and args.auto_hostname: print('You cannot use --hostname and --auto-hostname together.') sys.exit(-1) if not args.auto_hostname: hostname = args.hostname else: print('Trying to discover your hostname...') hostname = discover_hostname() if not hostname: print('Aborting because we could not discover your hostname.') print('Try again or run without --auto-hostname.') sys.exit(-1) print('Hostname discovered and set to {}'.format(hostname)) network = settings.NETWORK_NAME enable_sync_v1 = not args.x_sync_v2_only enable_sync_v2 = args.x_sync_v2_only or args.x_sync_bridge self.manager = HathorManager( reactor, peer_id=peer_id, network=network, hostname=hostname, tx_storage=self.tx_storage, wallet=self.wallet, wallet_index=args.wallet_index, stratum_port=args.stratum, ssl=True, checkpoints=settings.CHECKPOINTS, enable_sync_v1=enable_sync_v1, enable_sync_v2=enable_sync_v2, soft_voided_tx_ids=set(settings.SOFT_VOIDED_TX_IDS), ) if args.allow_mining_without_peers: self.manager.allow_mining_without_peers() if args.x_localhost_only: self.manager.connections.localhost_only = True dns_hosts = [] if settings.BOOTSTRAP_DNS: dns_hosts.extend(settings.BOOTSTRAP_DNS) if args.dns: dns_hosts.extend(args.dns) if dns_hosts: self.manager.add_peer_discovery(DNSPeerDiscovery(dns_hosts)) if args.bootstrap: self.manager.add_peer_discovery(BootstrapPeerDiscovery(args.bootstrap)) if args.test_mode_tx_weight: _set_test_mode(TestMode.TEST_TX_WEIGHT) if self.wallet: self.wallet.test_mode = True if args.x_full_verification: self.manager._full_verification = True if args.x_fast_init_beta: self.log.warn('--x-fast-init-beta is now the default, no need to specify it') for description in args.listen: self.manager.add_listen_address(description) self.start_manager(args) self.register_resources(args)
def _load_peer_id_pool( file_path: str = 'tests/peer_id_pool.json') -> Iterator[PeerId]: with open(file_path) as peer_id_pool_file: peer_id_pool_dict = json.load(peer_id_pool_file) for peer_id_dict in peer_id_pool_dict: yield PeerId.create_from_json(peer_id_dict)
def handle_peer_id(self, payload: str) -> Generator[Any, Any, None]: """ Executed when a PEER-ID is received. It basically checks the identity of the peer. Only after this step, the peer connection is considered established and ready to communicate. """ protocol = self.protocol data = json.loads(payload) peer = PeerId.create_from_json(data) peer.validate() assert peer.id is not None # If the connection URL had a peer-id parameter we need to check it's the same if protocol.expected_peer_id and peer.id != protocol.expected_peer_id: protocol.send_error_and_close_connection( 'Peer id different from the requested one.') return # is it on the whitelist? if peer.id and self._should_block_peer(peer.id): if settings.WHITELIST_WARN_BLOCKED_PEERS: protocol.send_error_and_close_connection( f'Blocked (by {peer.id}). Get in touch with Hathor team.') else: protocol.send_error_and_close_connection( 'Connection rejected.') return if peer.id == protocol.my_peer.id: protocol.send_error_and_close_connection('Are you my clone?!') return if protocol.connections is not None: if protocol.connections.is_peer_connected(peer.id): protocol.send_error_and_close_connection( 'We are already connected.') return entrypoint_valid = yield peer.validate_entrypoint(protocol) if not entrypoint_valid: protocol.send_error_and_close_connection( 'Connection string is not in the entrypoints.') return if protocol.use_ssl: certificate_valid = peer.validate_certificate(protocol) if not certificate_valid: protocol.send_error_and_close_connection( 'Public keys from peer and certificate are not the same.') return # If it gets here, the peer is validated, and we are ready to start communicating. protocol.peer = peer from hathor.p2p.netfilter import get_table from hathor.p2p.netfilter.context import NetfilterContext context = NetfilterContext( protocol=self.protocol, connections=self.protocol.connections, addr=self.protocol.transport.getPeer(), ) verdict = get_table('filter').get_chain('post_peerid').process(context) if not bool(verdict): self.protocol.disconnect( 'rejected by netfilter: filter post_peerid', force=True) return self.send_ready()