Minor environment variable improvements
- COIN and NET strip surrounding whitespace - new environment variable RPC_HOST, similar to HOST, but for RPC. Permits fine-grained control of which addresses the RPC server listens on. - HOST and RPC_HOST strip surrounding whitespace from hostnames and IP addresses - tests and documentation updated to match
This commit is contained in:
parent
0c2e5c6368
commit
131344715a
@ -8,6 +8,11 @@ given, the rest will have sensible defaults if not specified. Many of
|
||||
the defaults around resource usage are conservative; I encourage you
|
||||
to review them.
|
||||
|
||||
Note: by default the server will only serve to connections from the
|
||||
same machine. To be accessible to other users across the internet you
|
||||
must set **HOST** appropriately; see below.
|
||||
|
||||
|
||||
Required
|
||||
--------
|
||||
|
||||
@ -53,6 +58,7 @@ The following are required if you use the `run` script:
|
||||
|
||||
The username the server will run as.
|
||||
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
@ -63,12 +69,6 @@ These environment variables are optional:
|
||||
Must be a *NET* from one of the **Coin** classes in `lib/coins.py`_.
|
||||
Defaults to `mainnet`.
|
||||
|
||||
Note: if you are using Bitcoin Core post the August 1st fork, you
|
||||
should have NET be `bitcoin-segwit`, and if on the Bitcoin Cash
|
||||
chain NET should be `mainnet`.
|
||||
Note Bitcoin Core >= 0.13.1 requires a special *NET* for testnet:
|
||||
`testnet-segwit`.
|
||||
|
||||
* **DB_ENGINE**
|
||||
|
||||
Database engine for the UTXO and history database. The default is
|
||||
@ -76,13 +76,6 @@ These environment variables are optional:
|
||||
install the appropriate python package for your engine. The value
|
||||
is not case sensitive.
|
||||
|
||||
* **REORG_LIMIT**
|
||||
|
||||
The maximum number of blocks to be able to handle in a chain
|
||||
reorganisation. ElectrumX retains some fairly compact undo
|
||||
information for this many blocks in levelDB. The default is a
|
||||
function of **COIN** and **NET**; for Bitcoin mainnet it is 200.
|
||||
|
||||
* **HOST**
|
||||
|
||||
The host or IP address that the TCP and SSL servers will use when
|
||||
@ -101,20 +94,25 @@ These environment variables are optional:
|
||||
If set then SSL_CERTFILE and SSL_KEYFILE must be defined and be
|
||||
filesystem paths to those SSL files.
|
||||
|
||||
* **RPC_HOST**
|
||||
|
||||
The host or IP address that the RPC server will listen on and
|
||||
defaults to `localhost`. To listen on multiple specific addresses
|
||||
specify a comma-separated list. Servers with unusual networking
|
||||
setups might want to specify e.g. `::1` or `127.0.0.1` explicitly
|
||||
rather than defaulting to `localhost`.
|
||||
|
||||
An empty string (normally indicating all interfaces) is interpreted
|
||||
as `localhost`, because allowing access to the server's RPC
|
||||
interface to arbitrary connections aacross the internet is not a
|
||||
good idea.
|
||||
|
||||
* **RPC_PORT**
|
||||
|
||||
ElectrumX will listen on this port for local RPC connections.
|
||||
ElectrumX listens for RPC connections unless this is explicitly set
|
||||
to blank. The default is appropriate for **COIN** and **NET**
|
||||
(e.g., 8000 for Bitcoin mainnet) if not set.
|
||||
|
||||
* **EVENT_LOOP_POLICY**
|
||||
|
||||
The name of an event loop policy to replace the default asyncio
|
||||
policy, if any. At present only `uvloop` is accepted, in which case
|
||||
you must have installed the `uvloop`_ Python package.
|
||||
|
||||
If you are not sure what this means leave it unset.
|
||||
to blank. The default depends on **COIN** and **NET** (e.g., 8000
|
||||
for Bitcoin mainnet) if not set, as indicated in `lib/coins.py`_.
|
||||
|
||||
* **DONATION_ADDRESS**
|
||||
|
||||
@ -159,6 +157,22 @@ These environment variables are optional:
|
||||
that **ANON_LOGS** is honoured. Defaults to 3600. Set to zero to
|
||||
suppress this logging.
|
||||
|
||||
* **REORG_LIMIT**
|
||||
|
||||
The maximum number of blocks to be able to handle in a chain
|
||||
reorganisation. ElectrumX retains some fairly compact undo
|
||||
information for this many blocks in levelDB. The default is a
|
||||
function of **COIN** and **NET**; for Bitcoin mainnet it is 200.
|
||||
|
||||
* **EVENT_LOOP_POLICY**
|
||||
|
||||
The name of an event loop policy to replace the default asyncio
|
||||
policy, if any. At present only `uvloop` is accepted, in which case
|
||||
you must have installed the `uvloop`_ Python package.
|
||||
|
||||
If you are not sure what this means leave it unset.
|
||||
|
||||
|
||||
Resource Usage Limits
|
||||
---------------------
|
||||
|
||||
|
||||
@ -204,7 +204,7 @@ class Controller(util.LoggedClass):
|
||||
async def main_loop(self):
|
||||
'''Controller main loop.'''
|
||||
if self.env.rpc_port is not None:
|
||||
await self.start_server('RPC', ('127.0.0.1', '::1'),
|
||||
await self.start_server('RPC', self.env.cs_host(for_rpc=True),
|
||||
self.env.rpc_port)
|
||||
self.ensure_future(self.bp.main_loop())
|
||||
self.ensure_future(self.wait_for_bp_catchup())
|
||||
@ -292,7 +292,7 @@ class Controller(util.LoggedClass):
|
||||
self.state = self.LISTENING
|
||||
|
||||
env = self.env
|
||||
host = env.cs_host()
|
||||
host = env.cs_host(for_rpc=False)
|
||||
if env.tcp_port is not None:
|
||||
await self.start_server('TCP', host, env.tcp_port)
|
||||
if env.ssl_port is not None:
|
||||
@ -317,7 +317,8 @@ class Controller(util.LoggedClass):
|
||||
self.header_cache.clear()
|
||||
|
||||
# Make a copy; self.sessions can change whilst await-ing
|
||||
sessions = [s for s in self.sessions if isinstance(s, self.coin.SESSIONCLS)]
|
||||
sessions = [s for s in self.sessions
|
||||
if isinstance(s, self.coin.SESSIONCLS)]
|
||||
for session in sessions:
|
||||
await session.notify(self.bp.db_height, touched)
|
||||
|
||||
|
||||
@ -31,8 +31,8 @@ class Env(lib_util.LoggedClass):
|
||||
self.obsolete(['UTXO_MB', 'HIST_MB', 'NETWORK'])
|
||||
self.db_dir = self.required('DB_DIRECTORY')
|
||||
self.daemon_url = self.required('DAEMON_URL')
|
||||
coin_name = self.required('COIN')
|
||||
network = self.default('NET', 'mainnet')
|
||||
coin_name = self.required('COIN').strip()
|
||||
network = self.default('NET', 'mainnet').strip()
|
||||
self.coin = Coin.lookup_coin_class(coin_name, network)
|
||||
self.cache_MB = self.integer('CACHE_MB', 1200)
|
||||
self.host = self.default('HOST', 'localhost')
|
||||
@ -43,6 +43,7 @@ class Env(lib_util.LoggedClass):
|
||||
if self.ssl_port:
|
||||
self.ssl_certfile = self.required('SSL_CERTFILE')
|
||||
self.ssl_keyfile = self.required('SSL_KEYFILE')
|
||||
self.rpc_host = self.default('RPC_HOST', 'localhost')
|
||||
self.rpc_port = self.integer('RPC_PORT', 8000)
|
||||
self.max_subscriptions = self.integer('MAX_SUBSCRIPTIONS', 10000)
|
||||
self.banner_file = self.default('BANNER_FILE', None)
|
||||
@ -184,11 +185,20 @@ class Env(lib_util.LoggedClass):
|
||||
return uvloop.EventLoopPolicy()
|
||||
raise self.Error('unknown event loop policy "{}"'.format(policy))
|
||||
|
||||
def cs_host(self):
|
||||
def cs_host(self, *, for_rpc):
|
||||
'''Returns the 'host' argument to pass to asyncio's create_server
|
||||
call. The result can be a single host name string, a list of
|
||||
host name strings, or an empty string to bind to all interfaces.'''
|
||||
result = self.host.split(',')
|
||||
host name strings, or an empty string to bind to all interfaces.
|
||||
|
||||
If rpc is True the host to use for the RPC server is returned.
|
||||
Otherwise the host to use for SSL/TCP servers is returned.
|
||||
'''
|
||||
host = self.rpc_host if for_rpc else self.host
|
||||
result = [part.strip() for part in host.split(',')]
|
||||
if len(result) == 1:
|
||||
result = result[0]
|
||||
# An empty result indicates all interfaces, which is not
|
||||
# permitted for the RPC server.
|
||||
if for_rpc and not result:
|
||||
result = 'localhost'
|
||||
return result
|
||||
|
||||
@ -524,7 +524,7 @@ class PeerManager(util.LoggedClass):
|
||||
|
||||
# Use our listening Host/IP for outgoing connections so our
|
||||
# peers see the correct source.
|
||||
host = self.env.cs_host()
|
||||
host = self.env.cs_host(for_rpc=False)
|
||||
if isinstance(host, list):
|
||||
host = host[0]
|
||||
local_addr = (host, None) if host else None
|
||||
|
||||
@ -82,8 +82,11 @@ def test_COIN_NET():
|
||||
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'
|
||||
os.environ['COIN'] = ' Litecoin '
|
||||
e = Env()
|
||||
assert e.coin == lib_coins.Litecoin
|
||||
os.environ['NET'] = 'testnet'
|
||||
@ -97,10 +100,23 @@ def test_HOST():
|
||||
assert_default('HOST', 'host', 'localhost')
|
||||
os.environ['HOST'] = ''
|
||||
e = Env()
|
||||
assert e.cs_host() == ''
|
||||
assert e.cs_host(for_rpc=False) == ''
|
||||
os.environ['HOST'] = '192.168.0.1,23.45.67.89'
|
||||
e = Env()
|
||||
assert e.cs_host() == ['192.168.0.1', '23.45.67.89']
|
||||
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 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 test_REORG_LIMIT():
|
||||
assert_integer('REORG_LIMIT', 'reorg_limit',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user