1
0
mirror of https://github.com/romanz/electrs.git synced 2024-11-19 01:43:29 +01:00

Use configure_me instead of clap

Since use of configuration files is both mmore secure and more
convenient and clap doesn't support config files, this switches to
configure_me, which supports config files, env vars and also generating
man pages.

Closes #151
This commit is contained in:
Martin Habovstiak 2019-09-06 11:40:13 +02:00
parent a61e1b3b7a
commit ec049b9ad5
6 changed files with 354 additions and 174 deletions

100
Cargo.lock generated
View File

@ -138,6 +138,8 @@ dependencies = [
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
"secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_test 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -154,6 +156,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -170,6 +173,14 @@ dependencies = [
"constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "build-helper"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.3.2"
@ -244,6 +255,30 @@ dependencies = [
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "configure_me"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"parse_arg 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "configure_me_codegen"
version = "0.3.3"
dependencies = [
"build-helper 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fmt2io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"man 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.3"
@ -320,7 +355,8 @@ dependencies = [
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bitcoin 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"configure_me 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"configure_me_codegen 0.3.3",
"crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -404,6 +440,11 @@ dependencies = [
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fmt2io"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fnv"
version = "1.0.6"
@ -524,6 +565,14 @@ dependencies = [
"hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "man"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"roff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "matches"
version = "0.1.8"
@ -591,6 +640,11 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parse_arg"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
@ -762,6 +816,11 @@ dependencies = [
"librocksdb-sys 6.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "roff"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rust-crypto"
version = "0.2.36"
@ -821,6 +880,14 @@ dependencies = [
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.9.0"
@ -859,6 +926,14 @@ dependencies = [
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_test"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "shlex"
version = "0.1.1"
@ -994,6 +1069,14 @@ dependencies = [
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ucd-util"
version = "0.1.5"
@ -1015,6 +1098,11 @@ dependencies = [
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-segmentation"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.5"
@ -1134,6 +1222,7 @@ dependencies = [
"checksum bitcoin_hashes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b7a2e9773ee7ae7f2560f0426c938f57902dcb9e39321b0cbd608f47ed579a4"
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
"checksum build-helper 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdce191bf3fa4995ce948c8c83b4640a1745457a149e73c6db75b4ffe36aad5f"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02"
"checksum cexpr 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7fa24eb00d5ffab90eaeaf1092ac85c04c64aaf358ea6f84505b8116d24c6af"
@ -1143,6 +1232,7 @@ dependencies = [
"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum configure_me 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09bcca54d6219791a348ed074cb1599e47a29fbd33a23b2ba1dffc18231da6b1"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
@ -1157,6 +1247,7 @@ dependencies = [
"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum fmt2io 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db8691f0820ad11ce6eb94057d0dd9c456500da04da0c12a85c90d6f979cc9"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
@ -1174,6 +1265,7 @@ dependencies = [
"checksum librocksdb-sys 6.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6af56e6599bce586321e8ba8acf8a0a5e97431fd9ab49f9b69f92d93fe642c6"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum lru 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "aab390a5bd7ac223ced62fe224337c4748219145152174659291ea04ac8979c0"
"checksum man 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ccbbb1d623a3cbcaeef9a072f7ccbd6f8ca1e788f3e301d5c49bdd67b1f5a942"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
@ -1183,6 +1275,7 @@ dependencies = [
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
"checksum page_size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f89ef58b3d32420dbd1a43d2f38ae92f6239ef12bb556ab09ca55445f5a67242"
"checksum parse_arg 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0aa6995ee52a637a52261de3240eb3ffec0cfa24cb917cd03fc0365691ca24ae"
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
@ -1203,6 +1296,7 @@ dependencies = [
"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc"
"checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c"
"checksum rocksdb 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e7523c32e26bf2ebc4540645961dafcbd086c652e8ecb563a507f432eb7636d"
"checksum roff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e33e4fb37ba46888052c763e4ec2acfedd8f00f62897b630cadb6298b833675e"
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
@ -1212,11 +1306,13 @@ dependencies = [
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
"checksum secp256k1 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaccd3a23619349e0878d9a241f34b1982343cdf67367058cd7d078d326b63e"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113"
"checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c"
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
"checksum serde_test 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "f2d8999326d1f713002c52199b3f30c052dc8998d9359d5ae950328e527da1cd"
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
"checksum signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4f61c4d59f3aaa9f61bba6450a9b80ba48362fd7d651689e7a10c453b1f6dc68"
"checksum signal-hook-registry 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "913661ac8848a61e39684a3c3e7a7a14a4deec7f54b4976d0641e70dda3939b1"
@ -1233,9 +1329,11 @@ dependencies = [
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951"
"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"

View File

@ -10,6 +10,7 @@ keywords = ["bitcoin", "electrum", "server", "index", "database"]
documentation = "https://docs.rs/electrs/"
readme = "README.md"
edition = "2018"
build = "build.rs"
[profile.release]
lto = true
@ -21,9 +22,9 @@ latest_rust = [] # use latest Rust features (otherwise, support Rust 1.32)
arrayref = "0.3"
base64 = "0.10"
bincode = "1.0"
bitcoin = "0.18"
bitcoin = { version = "0.18", features = ["use-serde"] }
bitcoin_hashes = "0.3"
clap = "2.31"
configure_me = "0.3.2"
crossbeam-channel = "0.3"
dirs = "1.0"
error-chain = "0.12"
@ -45,3 +46,6 @@ stderrlog = "0.4.1"
sysconf = ">=0.3.4"
time = "0.1"
tiny_http = "0.6"
[build-dependencies]
configure_me_codegen = "0.3.4"

5
build.rs Normal file
View File

@ -0,0 +1,5 @@
extern crate configure_me_codegen;
fn main() {
configure_me_codegen::build_script_with_man("config_spec.toml").unwrap();
}

101
config_spec.toml Normal file
View File

@ -0,0 +1,101 @@
[general]
env_prefix = "ELECTRS"
doc = """
An efficient re-implementation of Electrum Server, inspired by ElectrumX, Electrum Personal Server and bitcoincore-indexd.
The motivation behind this project is to enable a user to run his own Electrum server, with required hardware resources not much beyond those of a full node. The server indexes the entire Bitcoin blockchain, and the resulting index enables fast queries for any given user wallet, allowing the user to keep real-time track of his balances and his transaction history using the Electrum wallet. Since it runs on the user's own machine, there is no need for the wallet to communicate with external Electrum servers, thus preserving the privacy of the user's addresses and balances."""
[[switch]]
name = "verbose"
abbr = "v"
doc = "Increase logging verbosity"
count = true
[[switch]]
name = "timestamp"
doc = "Prepend log lines with a timestamp"
[[param]]
name = "db_dir"
type = "std::path::PathBuf"
doc = "Directory to store index database (default: ./db/)"
default = "\"./db\".into()"
[[param]]
name = "daemon_dir"
type = "std::path::PathBuf"
doc = "Data directory of Bitcoind (default: ~/.bitcoin/)"
default = "crate::config::default_daemon_dir()"
[[param]]
name = "cookie"
type = "String"
doc = "JSONRPC authentication cookie ('USER:PASSWORD', default: read from ~/.bitcoin/.cookie)"
# Force the user to use config file in order to avoid password leaks
argument = false
env_var = false
[[param]]
name = "network"
type = "crate::config::BitcoinNetwork"
convert_into = "::bitcoin::network::constants::Network"
doc = "Select Bitcoin network type ('mainnet', 'testnet' or 'regtest')"
default = "Default::default()"
[[param]]
name = "electrum_rpc_addr"
type = "crate::config::ResolvAddr"
convert_into = "std::net::SocketAddr"
doc = "Electrum server JSONRPC 'addr:port' to listen on (default: '127.0.0.1:50001' for mainnet, '127.0.0.1:60001' for testnet and '127.0.0.1:60401' for regtest)"
[[param]]
name = "daemon_rpc_addr"
type = "crate::config::ResolvAddr"
convert_into = "std::net::SocketAddr"
doc = "Bitcoin daemon JSONRPC 'addr:port' to connect (default: 127.0.0.1:8332 for mainnet, 127.0.0.1:18332 for testnet and 127.0.0.1:18443 for regtest)"
[[param]]
name = "monitoring_addr"
type = "crate::config::ResolvAddr"
convert_into = "std::net::SocketAddr"
doc = "Prometheus monitoring 'addr:port' to listen on (default: 127.0.0.1:4224 for mainnet, 127.0.0.1:14224 for testnet and 127.0.0.1:24224 for regtest)"
[[switch]]
name = "jsonrpc_import"
doc = "Use JSONRPC instead of directly importing blk*.dat files. Useful for remote full node or low memory system"
[[param]]
name = "index_batch_size"
type = "usize"
doc = "Number of blocks to get in one JSONRPC request from bitcoind"
default = "100"
[[param]]
name = "bulk_index_threads"
type = "usize"
doc = "Number of threads used for bulk indexing (default: use the # of CPUs)"
default = "0"
[[param]]
name = "tx_cache_size"
type = "usize"
doc = "Number of transactions to keep in for query LRU cache"
default = "10000"
[[param]]
name = "blocktxids_cache_size"
type = "usize"
doc = "Number of blocks to cache transactions IDs in LRU cache"
default = "100"
[[param]]
name = "txid_limit"
type = "usize"
doc = "Number of transactions to lookup before returning an error, to prevent 'too popular' addresses from causing the RPC server to get stuck (0 - disable the limit)"
default = "100"
[[param]]
name = "server_banner"
type = "String"
doc = "The banner to be shown in the Electrum console"
default = "concat!(\"Welcome to electrs \", env!(\"CARGO_PKG_VERSION\"), \" (Electrum Rust Server)!\").to_owned()"

View File

@ -1,18 +1,114 @@
use bitcoin::network::constants::Network;
use clap::{App, Arg};
use dirs::home_dir;
use num_cpus;
use std::fs;
use std::fmt;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::sync::Arc;
use std::str::FromStr;
use std::ffi::{OsStr, OsString};
use std::convert::TryInto;
use stderrlog;
use crate::daemon::CookieGetter;
use crate::errors::*;
const DEFAULT_SERVER_ADDRESS: &str = "127.0.0.1"; // by default, serve on IPv4 localhost
const DEFAULT_SERVER_ADDRESS: [u8; 4] = [127, 0, 0, 1]; // by default, serve on IPv4 localhost
mod internal {
#![allow(unused)]
include!(concat!(env!("OUT_DIR"), "/configure_me_config.rs"));
}
pub enum AddressError {
InvalidUtf8(OsString),
ResolvError { addr: String, err: std::io::Error },
NoAddrError(String),
}
impl fmt::Display for AddressError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AddressError::InvalidUtf8(val) => write!(f, "{:?} isn't a valid UTF-8 sequence", val),
AddressError::ResolvError { addr, err } => write!(f, "Failed to resolve address {}: {}", addr, err),
AddressError::NoAddrError(addr) => write!(f, "No address found for {}", addr),
}
}
}
#[derive(Deserialize)]
pub struct ResolvAddr(SocketAddr);
impl ::configure_me::parse_arg::ParseArg for ResolvAddr {
type Error = AddressError;
fn parse_arg(arg: &OsStr) -> std::result::Result<Self, Self::Error> {
let arg = arg
.to_str()
.ok_or_else(|| AddressError::InvalidUtf8(arg.to_owned()))?;
arg
.to_socket_addrs().map_err(|err| AddressError::ResolvError { addr: arg.to_owned(), err })?
.next()
.ok_or_else(|| AddressError::NoAddrError(arg.to_owned()))
.map(ResolvAddr)
}
fn parse_owned_arg(arg: OsString) -> std::result::Result<Self, Self::Error> {
let arg = arg
.into_string()
.map_err(|orig| AddressError::InvalidUtf8(orig))?;
match arg.to_socket_addrs() {
Ok(mut iter) => iter.next().ok_or_else(|| AddressError::NoAddrError(arg)).map(ResolvAddr),
Err(err) => Err(AddressError::ResolvError { addr: arg, err }),
}
}
fn describe_type<W: fmt::Write>(mut writer: W) -> fmt::Result {
write!(writer, "a network address (will be resolved if needed)")
}
}
impl Into<SocketAddr> for ResolvAddr {
fn into(self) -> SocketAddr {
self.0
}
}
// `Network` uses "bitcoin" instead of "mainnet", so we have to reimplement it.
#[derive(Deserialize)]
pub struct BitcoinNetwork(Network);
impl Default for BitcoinNetwork {
fn default() -> Self {
BitcoinNetwork(Network::Bitcoin)
}
}
impl FromStr for BitcoinNetwork {
type Err = <Network as FromStr>::Err;
fn from_str(string: &str) -> std::result::Result<Self, Self::Err> {
Network::from_str(string).map(BitcoinNetwork)
}
}
impl ::configure_me::parse_arg::ParseArgFromStr for BitcoinNetwork {
fn describe_type<W: fmt::Write>(mut writer: W) -> std::fmt::Result {
write!(writer, "either 'bitcoin', 'testnet' or 'regtest'")
}
}
impl Into<Network> for BitcoinNetwork {
fn into(self) -> Network {
self.0
}
}
#[derive(Debug)]
pub struct Config {
@ -34,208 +130,86 @@ pub struct Config {
pub blocktxids_cache_size: usize,
}
fn str_to_socketaddr(address: &str, what: &str) -> SocketAddr {
address
.to_socket_addrs()
.unwrap_or_else(|e| panic!("unable to resolve {} address: {}", what, e))
.next()
.unwrap_or_else(|| panic!("no address found for {}", address))
fn default_daemon_dir() -> PathBuf {
// TODO: would be better to avoid expect()
let mut home = home_dir().expect("Unknown home directory");
home.push(".bitcoin");
home
}
impl Config {
pub fn from_args() -> Config {
let default_banner = format!(
"Welcome to electrs {} (Electrum Rust Server)!",
env!("CARGO_PKG_VERSION")
);
let m = App::new("Electrum Rust Server")
.version(crate_version!())
.arg(
Arg::with_name("verbosity")
.short("v")
.multiple(true)
.help("Increase logging verbosity"),
)
.arg(
Arg::with_name("timestamp")
.long("timestamp")
.help("Prepend log lines with a timestamp"),
)
.arg(
Arg::with_name("db_dir")
.long("db-dir")
.help("Directory to store index database (default: ./db/)")
.takes_value(true),
)
.arg(
Arg::with_name("daemon_dir")
.long("daemon-dir")
.help("Data directory of Bitcoind (default: ~/.bitcoin/)")
.takes_value(true),
)
.arg(
Arg::with_name("cookie")
.long("cookie")
.help("JSONRPC authentication cookie ('USER:PASSWORD', default: read from ~/.bitcoin/.cookie)")
.takes_value(true),
)
.arg(
Arg::with_name("network")
.long("network")
.help("Select Bitcoin network type ('mainnet', 'testnet' or 'regtest')")
.takes_value(true),
)
.arg(
Arg::with_name("electrum_rpc_addr")
.long("electrum-rpc-addr")
.help("Electrum server JSONRPC 'addr:port' to listen on (default: '127.0.0.1:50001' for mainnet, '127.0.0.1:60001' for testnet and '127.0.0.1:60401' for regtest)")
.takes_value(true),
)
.arg(
Arg::with_name("daemon_rpc_addr")
.long("daemon-rpc-addr")
.help("Bitcoin daemon JSONRPC 'addr:port' to connect (default: 127.0.0.1:8332 for mainnet, 127.0.0.1:18332 for testnet and 127.0.0.1:18443 for regtest)")
.takes_value(true),
)
.arg(
Arg::with_name("monitoring_addr")
.long("monitoring-addr")
.help("Prometheus monitoring 'addr:port' to listen on (default: 127.0.0.1:4224 for mainnet, 127.0.0.1:14224 for testnet and 127.0.0.1:24224 for regtest)")
.takes_value(true),
)
.arg(
Arg::with_name("jsonrpc_import")
.long("jsonrpc-import")
.help("Use JSONRPC instead of directly importing blk*.dat files. Useful for remote full node or low memory system"),
)
.arg(
Arg::with_name("index_batch_size")
.long("index-batch-size")
.help("Number of blocks to get in one JSONRPC request from bitcoind")
.default_value("100"),
)
.arg(
Arg::with_name("bulk_index_threads")
.long("bulk-index-threads")
.help("Number of threads used for bulk indexing (default: use the # of CPUs)")
.default_value("0")
)
.arg(
Arg::with_name("tx_cache_size")
.long("tx-cache-size")
.help("Number of transactions to keep in for query LRU cache")
.default_value("10000") // should be enough for a small wallet.
)
.arg(
Arg::with_name("blocktxids_cache_size")
.long("blocktxids-cache-size")
.help("Number of blocks to cache transactions IDs in LRU cache")
.default_value("100")) // Needs ~0.305MB per per block at 10k txs each
.arg(
Arg::with_name("txid_limit")
.long("txid-limit")
.help("Number of transactions to lookup before returning an error, to prevent \"too popular\" addresses from causing the RPC server to get stuck (0 - disable the limit)")
.default_value("100") // should take a few seconds on a HDD
)
.arg(
Arg::with_name("server_banner")
.long("server-banner")
.help("The banner to be shown in the Electrum console")
.default_value(&default_banner)
)
.get_matches();
use internal::ResultExt;
let network_name = m.value_of("network").unwrap_or("mainnet");
let network_type = match network_name {
"mainnet" => Network::Bitcoin,
"testnet" => Network::Testnet,
"regtest" => Network::Regtest,
_ => panic!("unsupported Bitcoin network: {:?}", network_name),
let system_config: &OsStr = "/etc/electrs/config.toml".as_ref();
let home_config = home_dir().map(|mut dir| { dir.push(".electrs/config.toml"); dir });
let configs = std::iter::once(system_config)
.chain(home_config.as_ref().map(AsRef::as_ref));
let (mut config, _) = internal::Config::including_optional_config_files(configs).unwrap_or_exit();
let network_name = match config.network {
Network::Bitcoin => "bitcoin",
Network::Testnet => "testnet",
Network::Regtest => "regtest",
};
let db_dir = Path::new(m.value_of("db_dir").unwrap_or("./db"));
let db_path = db_dir.join(network_name);
let default_daemon_port = match network_type {
config.db_dir.push(network_name);
let default_daemon_port = match config.network {
Network::Bitcoin => 8332,
Network::Testnet => 18332,
Network::Regtest => 18443,
};
let default_electrum_port = match network_type {
let default_electrum_port = match config.network {
Network::Bitcoin => 50001,
Network::Testnet => 60001,
Network::Regtest => 60401,
};
let default_monitoring_port = match network_type {
let default_monitoring_port = match config.network {
Network::Bitcoin => 4224,
Network::Testnet => 14224,
Network::Regtest => 24224,
};
let daemon_rpc_addr: SocketAddr = str_to_socketaddr(
m.value_of("daemon_rpc_addr").unwrap_or(&format!(
"{}:{}",
DEFAULT_SERVER_ADDRESS, default_daemon_port
)),
"Bitcoin RPC",
);
let electrum_rpc_addr: SocketAddr = str_to_socketaddr(
m.value_of("electrum_rpc_addr").unwrap_or(&format!(
"{}:{}",
DEFAULT_SERVER_ADDRESS, default_electrum_port
)),
"Electrum RPC",
);
let monitoring_addr: SocketAddr = str_to_socketaddr(
m.value_of("monitoring_addr").unwrap_or(&format!(
"{}:{}",
DEFAULT_SERVER_ADDRESS, default_monitoring_port
)),
"Prometheus monitoring",
);
let daemon_rpc_addr: SocketAddr = config.daemon_rpc_addr.unwrap_or((DEFAULT_SERVER_ADDRESS, default_daemon_port).into());
let electrum_rpc_addr: SocketAddr = config.electrum_rpc_addr.unwrap_or((DEFAULT_SERVER_ADDRESS, default_electrum_port).into());
let monitoring_addr: SocketAddr = config.monitoring_addr.unwrap_or((DEFAULT_SERVER_ADDRESS, default_monitoring_port).into());
let mut daemon_dir = m
.value_of("daemon_dir")
.map(PathBuf::from)
.unwrap_or_else(|| {
let mut default_dir = home_dir().expect("no homedir");
default_dir.push(".bitcoin");
default_dir
});
match network_type {
match config.network {
Network::Bitcoin => (),
Network::Testnet => daemon_dir.push("testnet3"),
Network::Regtest => daemon_dir.push("regtest"),
Network::Testnet => config.daemon_dir.push("testnet3"),
Network::Regtest => config.daemon_dir.push("regtest"),
}
let cookie = m.value_of("cookie").map(std::borrow::ToOwned::to_owned);
let mut log = stderrlog::new();
log.verbosity(m.occurrences_of("verbosity") as usize);
log.timestamp(if m.is_present("timestamp") {
log.verbosity(config.verbose.try_into().expect("Overflow: Running electrs on less than 32 bit devices is unsupported"));
log.timestamp(if config.timestamp {
stderrlog::Timestamp::Millisecond
} else {
stderrlog::Timestamp::Off
});
log.init().expect("logging initialization failed");
let mut bulk_index_threads = value_t_or_exit!(m, "bulk_index_threads", usize);
if bulk_index_threads == 0 {
bulk_index_threads = num_cpus::get();
// Could have been default, but it's useful to allow the user to specify 0 when overriding
// configs.
if config.bulk_index_threads == 0 {
config.bulk_index_threads = num_cpus::get();
}
let config = Config {
log,
network_type,
db_path,
daemon_dir,
network_type: config.network,
db_path: config.db_dir,
daemon_dir: config.daemon_dir,
daemon_rpc_addr,
cookie,
cookie: config.cookie,
electrum_rpc_addr,
monitoring_addr,
jsonrpc_import: m.is_present("jsonrpc_import"),
index_batch_size: value_t_or_exit!(m, "index_batch_size", usize),
bulk_index_threads,
tx_cache_size: value_t_or_exit!(m, "tx_cache_size", usize),
blocktxids_cache_size: value_t_or_exit!(m, "blocktxids_cache_size", usize),
txid_limit: value_t_or_exit!(m, "txid_limit", usize),
server_banner: value_t_or_exit!(m, "server_banner", String),
jsonrpc_import: config.jsonrpc_import,
index_batch_size: config.index_batch_size,
bulk_index_threads: config.bulk_index_threads,
tx_cache_size: config.tx_cache_size,
blocktxids_cache_size: config.blocktxids_cache_size,
txid_limit: config.txid_limit,
server_banner: config.server_banner,
};
eprintln!("{:?}", config);
config

View File

@ -1,7 +1,5 @@
#![recursion_limit = "1024"]
#[macro_use]
extern crate clap;
#[macro_use]
extern crate arrayref;
#[macro_use]