def assert_default(env_var, attr, default): setup_base_env() e = Env() assert getattr(e, attr) == default os.environ[env_var] = 'foo' e = Env() assert getattr(e, attr) == 'foo'
def test_ban_versions(): e = Env() assert e.drop_client is None ban_re = '1\.[0-2]\.\d+?[_\w]*' os.environ['DROP_CLIENT'] = ban_re e = Env() assert e.drop_client == re.compile(ban_re) assert e.drop_client.match("1.2.3_buggy_client") assert e.drop_client.match("1.3.0_good_client") is None
def assert_boolean(env_var, attr, default): e = Env() assert getattr(e, attr) == default os.environ[env_var] = 'foo' e = Env() assert getattr(e, attr) == True os.environ[env_var] = '' e = Env() assert getattr(e, attr) == False
def test_COIN_NET(): '''Test COIN and NET defaults and redirection.''' setup_base_env() e = Env() assert e.coin == lib_coins.BitcoinCash os.environ['NET'] = 'testnet' e = Env() assert e.coin == lib_coins.BitcoinCashTestnet os.environ['NET'] = ' testnet ' e = Env() assert e.coin == lib_coins.BitcoinCashTestnet os.environ.pop('NET') os.environ['COIN'] = ' Litecoin ' e = Env() assert e.coin == lib_coins.Litecoin os.environ['NET'] = 'testnet' e = Env() assert e.coin == lib_coins.LitecoinTestnet os.environ.pop('NET') os.environ['COIN'] = ' BitcoinGold ' e = Env() assert e.coin == lib_coins.BitcoinGold os.environ['NET'] = 'testnet' e = Env() assert e.coin == lib_coins.BitcoinGoldTestnet os.environ['NET'] = 'regtest' e = Env() assert e.coin == lib_coins.BitcoinGoldRegtest os.environ['COIN'] = ' LitecoinCash ' e = Env() assert e.coin == lib_coins.LitecoinCash
def assert_integer(env_var, attr, default=''): if default != '': e = Env() assert getattr(e, attr) == default value = random.randrange(5, 2000) os.environ[env_var] = str(value) + '.1' with pytest.raises(Env.Error): Env() os.environ[env_var] = str(value) e = Env() assert getattr(e, attr) == value
def test_BANNER_FILE(): e = Env() assert e.banner_file is None assert e.tor_banner_file is None os.environ['BANNER_FILE'] = 'banner_file' e = Env() assert e.banner_file == 'banner_file' assert e.tor_banner_file == 'banner_file' os.environ['TOR_BANNER_FILE'] = 'tor_banner_file' e = Env() assert e.banner_file == 'banner_file' assert e.tor_banner_file == 'tor_banner_file'
def test_PEER_DISCOVERY(): e = Env() assert e.peer_discovery == Env.PD_ON os.environ['PEER_DISCOVERY'] = ' ' e = Env() assert e.peer_discovery == Env.PD_OFF os.environ['PEER_DISCOVERY'] = 'ON' e = Env() assert e.peer_discovery == Env.PD_ON os.environ['PEER_DISCOVERY'] = 'self' e = Env() assert e.peer_discovery == Env.PD_SELF
def test_EVENT_LOOP_POLICY(): e = Env() assert e.loop_policy is None os.environ['EVENT_LOOP_POLICY'] = 'foo' with pytest.raises(Env.Error): Env() os.environ['EVENT_LOOP_POLICY'] = 'uvloop' try: Env() except ImportError: pass del os.environ['EVENT_LOOP_POLICY']
def main(): '''Set up logging and run the server.''' log_fmt = Env.default('LOG_FORMAT', '%(levelname)s:%(name)s:%(message)s') logging.basicConfig(level=logging.DEBUG, format=log_fmt) logging.info('ElectrumX server starting') try: controller = Controller(Env()) controller.run() except Exception: traceback.print_exc() logging.critical('ElectrumX server terminated abnormally') else: logging.info('ElectrumX server terminated normally')
def test_SSL_PORT(): # Requires both SSL_CERTFILE and SSL_KEYFILE to be set os.environ['SSL_PORT'] = '50002' os.environ['SSL_CERTFILE'] = 'certfile' with pytest.raises(Env.Error): Env() os.environ.pop('SSL_CERTFILE') os.environ['SSL_KEYFILE'] = 'keyfile' with pytest.raises(Env.Error): Env() os.environ['SSL_CERTFILE'] = 'certfile' os.environ.pop('SSL_PORT') assert_integer('SSL_PORT', 'ssl_port', None)
def test_HOST(): assert_default('HOST', 'host', 'localhost') os.environ['HOST'] = '' e = Env() assert e.cs_host(for_rpc=False) == '' os.environ['HOST'] = '192.168.0.1,23.45.67.89' e = Env() assert e.cs_host(for_rpc=False) == ['192.168.0.1', '23.45.67.89'] os.environ['HOST'] = '192.168.0.1 , 23.45.67.89 ' e = Env() assert e.cs_host(for_rpc=False) == ['192.168.0.1', '23.45.67.89']
def main_loop(): '''Start the server.''' if os.geteuid() == 0: raise Exception('DO NOT RUN AS ROOT! Create an unpriveleged user ' 'account and use that') loop = asyncio.get_event_loop() #loop.set_debug(True) def on_signal(signame): '''Call on receipt of a signal to cleanly shutdown.''' logging.warning('received {} signal, initiating shutdown' .format(signame)) controller.initiate_shutdown() def on_exception(loop, context): '''Suppress spurious messages it appears we cannot control.''' message = context.get('message') if not message in SUPPRESS_MESSAGES: if not ('task' in context and 'accept_connection2()' in repr(context.get('task'))): loop.default_exception_handler(context) controller = Controller(Env()) future = asyncio.ensure_future(controller.main_loop()) # Install signal handlers for signame in ('SIGINT', 'SIGTERM'): loop.add_signal_handler(getattr(signal, signame), partial(on_signal, signame)) # Install exception handler loop.set_exception_handler(on_exception) loop.run_until_complete(future) loop.close()
def main(): env = Env() bp = DB(env) coin = env.coin if len(sys.argv) == 1: count_entries(bp.hist_db, bp.utxo_db) return argc = 1 try: limit = int(sys.argv[argc]) argc += 1 except Exception: limit = 10 for addr in sys.argv[argc:]: print('Address: ', addr) hashX = coin.address_to_hashX(addr) for n, (tx_hash, height) in enumerate(bp.get_history(hashX, limit)): print('History #{:d}: hash: {} height: {:d}' .format(n + 1, hash_to_str(tx_hash), height)) n = None for n, utxo in enumerate(bp.get_utxos(hashX, limit)): print('UTXOs #{:d}: hash: {} pos: {:d} height: {:d} value: {:d}' .format(n + 1, hash_to_str(utxo.tx_hash), utxo.tx_pos, utxo.height, utxo.value)) if n is None: print('No UTXOs') balance = bp.get_balance(hashX) print('Balance: {} {}'.format(coin.decimal_value(balance), coin.SHORTNAME))
def main(): env = Env() os.chdir(env.db_dir) db = DB(env) coin = db.coin argc = 1 try: limit = int(sys.argv[argc]) argc += 1 except: limit = 10 for addr in sys.argv[argc:]: print('Address: ', addr) hash168 = coin.address_to_hash168(addr) n = None for n, (tx_hash, height) in enumerate(db.get_history(hash168, limit)): print('History #{:d}: hash: {} height: {:d}'.format( n + 1, bytes(reversed(tx_hash)).hex(), height)) if n is None: print('No history') n = None for n, utxo in enumerate(db.get_utxos(hash168, limit)): print('UTXOs #{:d}: hash: {} pos: {:d} height: {:d} value: {:d}'. format(n + 1, bytes(reversed(utxo.tx_hash)).hex(), utxo.tx_pos, utxo.height, utxo.value)) if n is None: print('No UTXOs') balance = db.get_balance(hash168) print('Balance: {} {}'.format(coin.decimal_value(balance), coin.SHORTNAME))
def main(): '''Set up logging and run the server.''' logging.basicConfig(level=logging.INFO) logging.info('ElectrumX server starting') try: controller = Controller(Env()) controller.run() except Exception: traceback.print_exc() logging.critical('ElectrumX server terminated abnormally') else: logging.info('ElectrumX server terminated normally')
def main(): '''Set up logging and run the server.''' #logging.basicConfig(level=logging.DEBUG) logging.basicConfig(filename='aaa.log', level=logging.DEBUG, filemode='w') logging.info('ElectrumX server starting') try: controller = Controller(Env()) controller.run() except Exception: traceback.print_exc() logging.critical('ElectrumX server terminated abnormally') else: logging.info('ElectrumX server terminated normally')
def main(): '''Set up logging and run the server.''' logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-7s %(message)-100s ' '[%(filename)s:%(lineno)d]') logging.info('ElectrumX server starting') try: controller = Controller(Env()) controller.run() except Exception: traceback.print_exc() logging.critical('ElectrumX server terminated abnormally') else: logging.info('ElectrumX server terminated normally')
def run_test(db_dir): environ.clear() environ['DB_DIRECTORY'] = db_dir environ['DAEMON_URL'] = '' environ['COIN'] = 'BitcoinCash' env = Env() db = DB(env) # Test abstract compaction check_hashX_compaction(db) # Now test in with random data histories = create_histories(db) check_written(db, histories) compact_history(db) check_written(db, histories)
def test_RPC_HOST(): assert_default('RPC_HOST', 'rpc_host', 'localhost') os.environ['RPC_HOST'] = '' e = Env() # Blank reverts to localhost assert e.cs_host(for_rpc=True) == 'localhost' os.environ['RPC_HOST'] = '127.0.0.1, ::1' e = Env() assert e.cs_host(for_rpc=True) == ['127.0.0.1', '::1']
def compact_history(): if sys.version_info < (3, 6): raise RuntimeError('Python >= 3.6 is required to run ElectrumX') environ['DAEMON_URL'] = '' # Avoid Env erroring out env = Env() db = DB(env) assert not db.first_sync # Continue where we left off, if interrupted if db.comp_cursor == -1: db.comp_cursor = 0 db.comp_flush_count = max(db.comp_flush_count, 1) limit = 8 * 1000 * 1000 while db.comp_cursor != -1: db._compact_history(limit)
def main_loop(): '''Get tasks; loop until complete.''' if os.geteuid() == 0: raise Exception('DO NOT RUN AS ROOT! Create an unpriveleged user ' 'account and use that') env = Env() logging.info('switching current directory to {}'.format(env.db_dir)) os.chdir(env.db_dir) server = Server(env) tasks = server.async_tasks() loop = asyncio.get_event_loop() try: loop.run_until_complete(asyncio.gather(*tasks)) except asyncio.CancelledError: logging.warning('task cancelled; asyncio event loop closing') finally: loop.close()
def compact_history(): if sys.version_info < (3, 6): raise RuntimeError('Python >= 3.6 is required to run ElectrumX') environ['DAEMON_URL'] = '' # Avoid Env erroring out env = Env() db = DB(env) assert not db.first_sync history = db.history # Continue where we left off, if interrupted if history.comp_cursor == -1: history.comp_cursor = 0 history.comp_flush_count = max(history.comp_flush_count, 1) limit = 8 * 1000 * 1000 while history.comp_cursor != -1: history._compact_history(limit) # When completed also update the UTXO flush count db.set_flush_count(history.flush_count)
def test_tor_identity(): tor_host = 'something.onion' os.environ.pop('REPORT_HOST', None) os.environ.pop('REPORT_HOST_TOR', None) e = Env() assert len(e.identities) == 0 os.environ['REPORT_HOST_TOR'] = 'foo' os.environ['REPORT_SSL_PORT_TOR'] = '123' os.environ['TCP_PORT'] = '456' with pytest.raises(Env.Error): Env() os.environ['REPORT_HOST_TOR'] = tor_host e = Env() assert len(e.identities) == 1 ident = e.identities[0] assert ident.host == tor_host assert ident.tcp_port == 456 assert ident.ssl_port == 123 assert ident.nick_suffix == '_tor' os.environ['REPORT_TCP_PORT_TOR'] = os.environ['REPORT_SSL_PORT_TOR'] with pytest.raises(Env.Error): Env() os.environ['REPORT_HOST'] = 'foo.com' os.environ['TCP_PORT'] = '456' os.environ['SSL_PORT'] = '789' os.environ['REPORT_TCP_PORT'] = '654' os.environ['REPORT_SSL_PORT'] = '987' os.environ['SSL_CERTFILE'] = 'certfile' os.environ['SSL_KEYFILE'] = 'keyfile' os.environ.pop('REPORT_TCP_PORT_TOR', None) os.environ.pop('REPORT_SSL_PORT_TOR', None) e = Env() assert len(e.identities) == 2 ident = e.identities[1] assert ident.host == tor_host assert ident.tcp_port == 654 assert ident.ssl_port == 987 os.environ['REPORT_TCP_PORT_TOR'] = '234' os.environ['REPORT_SSL_PORT_TOR'] = '432' e = Env() assert len(e.identities) == 2 ident = e.identities[1] assert ident.host == tor_host assert ident.tcp_port == 234 assert ident.ssl_port == 432
def test_DAEMON_URL(): assert_required('DAEMON_URL') setup_base_env() e = Env() assert e.daemon_url == BASE_DAEMON_URL
def test_DB_DIRECTORY(): assert_required('DB_DIRECTORY') setup_base_env() e = Env() assert e.db_dir == BASE_DB_DIR
def test_minimal(): setup_base_env() Env()
def test_MAX_SESSIONS(): too_big = 1000000 os.environ['MAX_SESSIONS'] = str(too_big) e = Env() assert e.max_sessions < too_big
def assert_required(env_var): setup_base_env() os.environ.pop(env_var, None) with pytest.raises(Env.Error): Env()
def test_clearnet_identity(): os.environ['REPORT_TCP_PORT'] = '456' e = Env() assert len(e.identities) == 0 os.environ['REPORT_HOST'] = '8.8.8.8' e = Env() assert len(e.identities) == 1 assert e.identities[0].host == '8.8.8.8' os.environ['REPORT_HOST'] = 'localhost' with pytest.raises(Env.Error): Env() os.environ['REPORT_HOST'] = '' with pytest.raises(Env.Error): Env() os.environ['REPORT_HOST'] = '127.0.0.1' with pytest.raises(Env.Error): Env() os.environ['REPORT_HOST'] = '0.0.0.0' with pytest.raises(Env.Error): Env() os.environ['REPORT_HOST'] = '224.0.0.2' with pytest.raises(Env.Error): Env() os.environ['REPORT_HOST'] = '$HOST' with pytest.raises(Env.Error): Env() # Accept private IP, unless PEER_ANNOUNCE os.environ['PEER_ANNOUNCE'] = '' os.environ['REPORT_HOST'] = '192.168.0.1' os.environ['SSL_CERTFILE'] = 'certfile' os.environ['SSL_KEYFILE'] = 'keyfile' Env() os.environ['PEER_ANNOUNCE'] = 'OK' with pytest.raises(Env.Error) as err: Env() os.environ.pop('PEER_ANNOUNCE', None) assert 'not a valid REPORT_HOST' in str(err) os.environ['REPORT_HOST'] = '1.2.3.4' os.environ['REPORT_SSL_PORT'] = os.environ['REPORT_TCP_PORT'] with pytest.raises(Env.Error) as err: Env() assert 'both resolve' in str(err) os.environ['REPORT_SSL_PORT'] = '457' os.environ['REPORT_HOST'] = 'foo.com' e = Env() assert len(e.identities) == 1 ident = e.identities[0] assert ident.host == 'foo.com' assert ident.tcp_port == 456 assert ident.ssl_port == 457 assert ident.nick_suffix == ''