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'
Beispiel #2
0
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
Beispiel #4
0
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']
Beispiel #9
0
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')
Beispiel #10
0
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']
Beispiel #12
0
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()
Beispiel #13
0
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))
Beispiel #14
0
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')
Beispiel #16
0
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')
Beispiel #17
0
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)
Beispiel #21
0
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 == ''