electrs: adapt to version 0.9.0

- `waitfornewblock` was previously not included in the public RPC
  whitelist because it's reserved for testing and marked as hidden
  in bitcoind.

- electrs changed its verbosity settings. `-vv` is now the best choice
  for normal usage.

- bitcoind option `dataDirReadableByGroup` is now unused.
  Because it can be valuable for other use cases and implementing
  it is intricate, we're keeping it for now.

- test: keep `nc` connection open because otherwise the electrs
  RPC server would now close the connection before sending a response.
This commit is contained in:
Erik Arvstedt 2021-10-05 16:52:02 +02:00
parent 6f42fa8181
commit 75b89f3957
No known key found for this signature in database
GPG Key ID: 33312B944DD97846
9 changed files with 60 additions and 31 deletions

View File

@ -93,10 +93,6 @@
### ELECTRS ### ELECTRS
# Set this to enable electrs, an efficient Electrum server implemented in Rust. # Set this to enable electrs, an efficient Electrum server implemented in Rust.
# services.electrs.enable = true; # services.electrs.enable = true;
#
# If you have more than 8GB memory, enable this option so electrs will
# sync faster. Only available if hardware wallets are disabled.
# services.electrs.high-memory = true;
### BTCPayServer ### BTCPayServer
# Set this to enable BTCPayServer, a self-hosted, open-source # Set this to enable BTCPayServer, a self-hosted, open-source
@ -150,7 +146,6 @@
### Hardware wallets ### Hardware wallets
# Enable the following to allow using hardware wallets. # Enable the following to allow using hardware wallets.
# See https://github.com/bitcoin-core/HWI for more information. # See https://github.com/bitcoin-core/HWI for more information.
# Only available if electrs.high-memory is disabled.
# #
# Ledger must be initialized through the official ledger live app and the Bitcoin app must # Ledger must be initialized through the official ledger live app and the Bitcoin app must
# be installed and running on the device. # be installed and running on the device.
@ -264,5 +259,5 @@
# The nix-bitcoin release version that your config is compatible with. # The nix-bitcoin release version that your config is compatible with.
# When upgrading to a backwards-incompatible release, nix-bitcoin will display an # When upgrading to a backwards-incompatible release, nix-bitcoin will display an
# an error and provide hints for migrating your config to the new release. # an error and provide hints for migrating your config to the new release.
nix-bitcoin.configVersion = "0.0.51"; nix-bitcoin.configVersion = "0.0.53";
} }

View File

@ -25,6 +25,7 @@
"gettxoutsetinfo" "gettxoutsetinfo"
"scantxoutset" "scantxoutset"
"verifytxoutproof" "verifytxoutproof"
"waitfornewblock"
# Mining # Mining
"getblocktemplate" "getblocktemplate"
"getmininginfo" "getmininginfo"

View File

@ -19,13 +19,6 @@ let
default = "/var/lib/electrs"; default = "/var/lib/electrs";
description = "The data directory for electrs."; description = "The data directory for electrs.";
}; };
high-memory = mkOption {
type = types.bool;
default = false;
description = ''
If enabled, the electrs service will sync faster on high-memory systems ( 8GB).
'';
};
monitoringPort = mkOption { monitoringPort = mkOption {
type = types.port; type = types.port;
default = 4224; default = 4224;
@ -63,7 +56,12 @@ in {
} }
]; ];
services.bitcoind.enable = true; services.bitcoind = {
enable = true;
# Enable p2p connections
listen = true;
extraConfig = "whitelist=download@${nbLib.address cfg.address}";
};
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -"
@ -80,37 +78,31 @@ in {
serviceConfig = nbLib.defaultHardening // { serviceConfig = nbLib.defaultHardening // {
RuntimeDirectory = "electrs"; RuntimeDirectory = "electrs";
RuntimeDirectoryMode = "700"; RuntimeDirectoryMode = "700";
# electrs only uses the working directory for reading electrs.toml
WorkingDirectory = "/run/electrs"; WorkingDirectory = "/run/electrs";
ExecStart = '' ExecStart = ''
${config.nix-bitcoin.pkgs.electrs}/bin/electrs -vvv \ ${config.nix-bitcoin.pkgs.electrs}/bin/electrs -vv \
${if cfg.high-memory then
traceIf (!bitcoind.dataDirReadableByGroup) ''
Warning: For optimal electrs syncing performance, enable services.bitcoind.dataDirReadableByGroup.
Note that this disables wallet support in bitcoind.
'' ""
else
"--jsonrpc-import --index-batch-size=10"
} \
--network=${bitcoind.makeNetworkName "bitcoin" "regtest"} \ --network=${bitcoind.makeNetworkName "bitcoin" "regtest"} \
--db-dir='${cfg.dataDir}' \ --db-dir='${cfg.dataDir}' \
--daemon-dir='${bitcoind.dataDir}' \ --daemon-dir='${bitcoind.dataDir}' \
--electrum-rpc-addr=${cfg.address}:${toString cfg.port} \ --electrum-rpc-addr=${cfg.address}:${toString cfg.port} \
--monitoring-addr=${cfg.address}:${toString cfg.monitoringPort} \ --monitoring-addr=${cfg.address}:${toString cfg.monitoringPort} \
--daemon-rpc-addr=${nbLib.addressWithPort bitcoind.rpc.address bitcoind.rpc.port} \ --daemon-rpc-addr=${nbLib.addressWithPort bitcoind.rpc.address bitcoind.rpc.port} \
--daemon-p2p-addr=${nbLib.addressWithPort bitcoind.address bitcoind.port} \
${cfg.extraArgs} ${cfg.extraArgs}
''; '';
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
Restart = "on-failure"; Restart = "on-failure";
RestartSec = "10s"; RestartSec = "10s";
ReadWritePaths = "${cfg.dataDir} ${if cfg.high-memory then "${bitcoind.dataDir}" else ""}"; ReadWritePaths = cfg.dataDir;
} // nbLib.allowedIPAddresses cfg.enforceTor; } // nbLib.allowedIPAddresses cfg.enforceTor;
}; };
users.users.${cfg.user} = { users.users.${cfg.user} = {
isSystemUser = true; isSystemUser = true;
group = cfg.group; group = cfg.group;
extraGroups = [ "bitcoinrpc-public" ] ++ optionals cfg.high-memory [ bitcoind.user ]; extraGroups = [ "bitcoinrpc-public" ];
}; };
users.groups.${cfg.group} = {}; users.groups.${cfg.group} = {};
}; };

View File

@ -38,7 +38,6 @@ in {
{ assertion = (config.services.bitcoind.disablewallet == null || !config.services.bitcoind.disablewallet); { assertion = (config.services.bitcoind.disablewallet == null || !config.services.bitcoind.disablewallet);
message = '' message = ''
Hardware-Wallets are not compatible with bitcoind.disablewallet. Hardware-Wallets are not compatible with bitcoind.disablewallet.
Note that this option is active when enabling electrs.high-memory.
''; '';
} }
]; ];

View File

@ -26,5 +26,12 @@ in {
(mkRenamedAnnounceTorOption "clightning") (mkRenamedAnnounceTorOption "clightning")
(mkRenamedAnnounceTorOption "lnd") (mkRenamedAnnounceTorOption "lnd")
# 0.0.53
(mkRemovedOptionModule [ "services" "electrs" "high-memory" ] ''
This option is no longer supported by electrs 0.9.0. Electrs now always uses
bitcoin peer connections for syncing blocks. This performs well on low and high
memory systems.
'')
]; ];
} }

View File

@ -35,7 +35,6 @@ in {
services.bitcoind = { services.bitcoind = {
enable = true; enable = true;
listen = true; listen = true;
dataDirReadableByGroup = mkIf cfg.electrs.high-memory true;
dbCache = 1000; dbCache = 1000;
}; };

View File

@ -138,6 +138,37 @@ let
[1] https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/fidelity-bonds.md [1] https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/fidelity-bonds.md
''; '';
} }
{
version = "0.0.53";
condition = config.services.electrs.enable;
message = let
dbPath = "${config.services.electrs.dataDir}/mainnet";
in ''
Electrs 0.9.0 has switched to a new, more space efficient database format,
reducing storage demands by ~60% [1].
When started, electrs will automatically reindex the bitcoin blockchain.
This can take a few hours, depending on your hardware. The electrs server is
inactive during reindexing.
To upgrade, do the following:
- If you have less than 40 GB of free space [2] on the electrs data dir volume:
1. Delete the database:
systemctl stop electrs
rm -r '${dbPath}'
2. Deploy the new system config to your node
- Otherwise:
1. Deploy the new system config to your node
2. Check that electrs works as expected and delete the old database:
rm -r '${dbPath}'
[1] https://github.com/romanz/electrs/blob/557911e3baf9a000f883a6f619f0518945a7678d/doc/usage.md#upgrading
[2] This is based on the bitcoin blockchain size as of 2021-09.
The general formula is, approximately, size_of(${dbPath}) * 0.6
This includes the final database size (0.4) plus some extra storage (0.2).
'';
}
]; ];
mkOnionServiceChange = service: { mkOnionServiceChange = service: {

View File

@ -74,6 +74,8 @@ let
tests.charge-lnd = cfg.charge-lnd.enable; tests.charge-lnd = cfg.charge-lnd.enable;
tests.electrs = cfg.electrs.enable; tests.electrs = cfg.electrs.enable;
# Sigterm is broken during IBD in version 0.9.0 https://github.com/romanz/electrs/issues/532
systemd.services.electrs.serviceConfig.KillSignal = "SIGKILL";
tests.liquidd = cfg.liquidd.enable; tests.liquidd = cfg.liquidd.enable;
services.liquidd.extraConfig = mkIf config.test.noConnections "connect=0"; services.liquidd.extraConfig = mkIf config.test.noConnections "connect=0";

View File

@ -106,10 +106,13 @@ def _():
assert_running("electrs") assert_running("electrs")
wait_for_open_port(ip("electrs"), 4224) # prometeus metrics provider wait_for_open_port(ip("electrs"), 4224) # prometeus metrics provider
# Check RPC connection to bitcoind # Check RPC connection to bitcoind
machine.wait_until_succeeds(log_has_string("electrs", "NetworkInfo")) if not "regtest" in enabled_tests:
machine.wait_until_succeeds(
log_has_string("electrs", "waiting for 0 blocks to download")
)
# Impure: Stops electrs # Impure: Stops electrs
# Stop electrs from spamming the test log with 'WARN - wait until IBD is over' messages # Stop electrs from spamming the test log with 'waiting for 0 blocks to download' messages
@test("stop-electrs") @test("stop-electrs")
def _(): def _():
succeed("systemctl stop electrs") succeed("systemctl stop electrs")
@ -353,10 +356,10 @@ def _():
if enabled("electrs"): if enabled("electrs"):
machine.wait_for_unit("onion-addresses") machine.wait_for_unit("onion-addresses")
machine.wait_until_succeeds(log_has_string("electrs", "BlockchainInfo")) machine.wait_until_succeeds(log_has_string("electrs", "serving Electrum RPC"))
get_block_height_cmd = ( get_block_height_cmd = (
"""echo '{"method": "blockchain.headers.subscribe", "id": 0, "params": []}'""" """echo '{"method": "blockchain.headers.subscribe", "id": 0, "params": []}'"""
f" | nc -N {ip('electrs')} 50001 | jq -M .result.height" f" | nc {ip('electrs')} 50001 | head -1 | jq -M .result.height"
) )
assert_full_match(get_block_height_cmd, "10\n") assert_full_match(get_block_height_cmd, "10\n")
if enabled("clightning"): if enabled("clightning"):